標(biāo)識(shí)符 合法的標(biāo)識(shí)符是由字母,數(shù)字,下劃線組成,并且第一個(gè)標(biāo)識(shí)符必須為字母或是下劃線,不可以是數(shù)字。 標(biāo)識(shí)符分為關(guān)鍵字、預(yù)定義標(biāo)識(shí)符、用戶標(biāo)識(shí)符三類。 關(guān)鍵字都是用小寫(xiě)英文字母表示,共有31個(gè),不允許用戶將其用做變量名使用; 預(yù)定義標(biāo)識(shí)符被用做庫(kù)函數(shù)名和預(yù)編譯命令,比如:define scanf printf include; 用戶標(biāo)識(shí)符是程序員根據(jù)自己的需要定義的一類標(biāo)識(shí)符。 數(shù)據(jù)類型及占位 基本數(shù)據(jù)類型:char(1)、int(4) 、long(4)、short(2)、double(8)、float(4)、bool(1) 結(jié)構(gòu)類型:struct(累加)、union(共享)、int iArr[10] (40) 指針類型:int *p(4)、char **p(4)、void *p(4) 空類型:void 結(jié)構(gòu)體的占位大小是由內(nèi)部成員占位大小累加決定的,共用體(聯(lián)合體)的大小是由占位最大的內(nèi)部成員決定的。 字符常量 字符常量是用一對(duì)單引號(hào)括起來(lái)的一個(gè)字符,如‘a(chǎn)’、‘=’。 C語(yǔ)言中一個(gè)字符占用一個(gè)字節(jié),但該字節(jié)中存放的并非此字節(jié)本身,而是該字符所在機(jī)器采用的字符集的代碼。 大多數(shù)系統(tǒng)采用ASCII代碼字符集,如‘a(chǎn)’的ASII值為97,所以字符常量可以像整數(shù)一樣參與運(yùn)算。 轉(zhuǎn)義字符 C語(yǔ)言中還有一類轉(zhuǎn)義字符,以反斜杠‘\’開(kāi)始。轉(zhuǎn)義字符分為三種:一般轉(zhuǎn)義字符、八進(jìn)制轉(zhuǎn)義字符和十六進(jìn)制轉(zhuǎn)義字符。 一般轉(zhuǎn)義字符:用來(lái)表示那些不能顯示的ASCII字符, 比如‘\0’,‘\t’等。 八進(jìn)制轉(zhuǎn)義字符:由反斜杠‘\’和隨后的1~3個(gè)八進(jìn)制數(shù)字構(gòu)成的字符序列(如果你愿意可以在八進(jìn)制數(shù)字前面加上一個(gè)0來(lái)表示八進(jìn)制轉(zhuǎn)移字符)。如‘\144’和‘\101’分別表示‘a(chǎn)’和‘A’。 十六進(jìn)制轉(zhuǎn)義字符:由反斜杠‘\’和字母x(或X)及隨后的1~2個(gè)十六進(jìn)制數(shù)字構(gòu)成的字符序列。如‘\x41’和‘\X61’分別表示字符‘A’和‘a(chǎn)’。 字符串常量 字符串常量是用雙引號(hào)括起來(lái)的字符序列,字符串常量占用的內(nèi)存字節(jié)數(shù)等于字符串中字節(jié)數(shù)加1,增加的一個(gè)字節(jié)中存放‘\0',這是字符串結(jié)束的標(biāo)志。 變量的作用域 C語(yǔ)言中所有的變量都有自己的作用域,按照作用域的不同,變量可以分為局部變量和全局變量。 局部變量:只在函數(shù)內(nèi)部有效,其作用域僅限于函數(shù)內(nèi),離開(kāi)函數(shù)后再使用這種變量就是錯(cuò)誤的; 全局變量:全局變量不再屬于哪個(gè)函數(shù),它的有效范圍是從該變量定義的位置處開(kāi)始直到源文件的結(jié)束。 在一個(gè)函數(shù)之前定義的全局變量,在函數(shù)內(nèi)無(wú)需說(shuō)明就可以使用。 但是如果在該函數(shù)內(nèi)定義了一個(gè)與之前定義的全局變量同名的變量, 那么這個(gè)同名局部變量會(huì)在函數(shù)內(nèi)部屏蔽全局變量的影響。 int i = 1; void main() { int i = i; printf(“%d\n”,i); } main()內(nèi)部定義了一個(gè)和全局變量相同的局部變量i,局部變量會(huì)屏蔽全局變量的影響。那么,局部變量i和main()外的i無(wú)關(guān),是一個(gè)未定義的值。 變量的存儲(chǔ)類型 存儲(chǔ)類型是指變量占用內(nèi)存空間的方式,分為靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)。 靜態(tài)存儲(chǔ)的變量在變量定義時(shí)就為其分配了固定的存儲(chǔ)單元并一直保持不變,直至整個(gè)程序結(jié)束, 靜態(tài)變量和全局變量屬于靜態(tài)存儲(chǔ)方式; 動(dòng)態(tài)存儲(chǔ)的變量在程序的執(zhí)行過(guò)程中,僅當(dāng)需要時(shí)才臨時(shí)性的分配存儲(chǔ)單元, 并且在使用完畢,動(dòng)態(tài)存儲(chǔ)的變量會(huì)立即釋放,函數(shù)中定義的局部變量屬于動(dòng)態(tài)存儲(chǔ)方式。 靜態(tài)變量分為靜態(tài)局部變量和靜態(tài)外部變量,靜態(tài)局部變量是在函數(shù)內(nèi)部定義的, 靜態(tài)外部變量和全局變量一樣都是在函數(shù)外部定義的。 靜態(tài)局部變量: 1、靜態(tài)局部變量屬于靜態(tài)存儲(chǔ)類別,在靜態(tài)存儲(chǔ)區(qū)內(nèi)分配存儲(chǔ)單元,在整個(gè)程序的運(yùn)行期間都不釋放; 2、靜態(tài)局部變量是在編譯時(shí)賦初值的,即只賦初值一次; 3、如果定義局部變量時(shí)不賦初值,對(duì)靜態(tài)變量來(lái)說(shuō),編譯器會(huì)自動(dòng)賦初值0; 4、雖然靜態(tài)局部變量在函數(shù)調(diào)用結(jié)束后仍然存在,但其它的函數(shù)是不能引用它的。 void f() { static int num = 4; printf("%d",num); num++; } void main() { for(int i=0;i<3;i++) { f(); printf("\n"); } } 程序的輸出結(jié)果為:4 5 6,如果將關(guān)鍵字static去掉,程序的輸出結(jié)果為:4 4 4。 靜態(tài)外部變量: 1. 有些外部變量不希望被其他文件所引用,可以在變量定義時(shí)用static修飾,表示該變量為靜態(tài)外部變量。 2. 靜態(tài)外部變量只能在本文件中被引用,這種限制條件提高了程序的健壯性和安全性。 //file1.c static int a,b; //file2.c extern int a,b; void func(int x) { x = a+b; } 文件file2.c中聲明了兩個(gè)外部變量,并在函數(shù)func()中去使用它們。 因此編譯器在編譯程序時(shí)會(huì)到其它文件中去找,結(jié)果發(fā)現(xiàn)file1.c中的兩個(gè)變量被static所修飾,因此不能使用, 于是程序就會(huì)拋出編譯錯(cuò)誤 運(yùn)算符的優(yōu)先級(jí) 運(yùn)算符 解釋 結(jié)合方式 () [] -> . 括號(hào),函數(shù)參數(shù),數(shù)組下標(biāo),結(jié)構(gòu)體成員訪問(wèn) 由左向右 ! ~ ++ -- + - * & (type) sizeof 邏輯否,按位否,自增,自減,正負(fù) 由右向左 * / % 乘 除 取模 由左向右 + - 加 減 由左向右 << >> 加 減 由左向右 < <= >= > 小于 小于等于 大于等于 大于 由左向右 == != 等于 不等于 由左向右 & 按位與 由左向右 ^ 按位異或 由左向右 | 按位或 由左向右 && 邏輯與 由左向右 || 邏輯或 由左向右 : 條件 由右向左 = += -= *= /= &= ^= |= <<= >>= 各種賦值 由右向左 , 逗號(hào) 由左向右 位運(yùn)算 位運(yùn)算符一共有6個(gè),分別是‘&’、‘|’、‘^’、‘~’、‘<<’和‘>>’。 ‘~’是單目運(yùn)算符,其優(yōu)先級(jí)高于其它5個(gè)雙目運(yùn)算符。 移位運(yùn)算符的優(yōu)先級(jí)要高于雙目的按位運(yùn)算符。 雙目按位運(yùn)算符的優(yōu)先級(jí)從高低為:‘&’、‘^’、‘|’。 自增自減運(yùn)算符 使用自增自減運(yùn)算符要注意一下幾點(diǎn): 1、該運(yùn)算符只能用于變量,不能用于常量和表達(dá)式。 ++5; 這種寫(xiě)法是錯(cuò)誤的。 2、應(yīng)該避免在同一個(gè)表達(dá)式中對(duì)同一個(gè)變量多次使用該運(yùn)算符, 因?yàn)楸磉_(dá)式的求值順序不確定完全取決于編譯器,會(huì)產(chǎn)生意想不到的結(jié)果。 (i++)+(i++)+(i--); 設(shè)i的值為10,因?yàn)?個(gè)表達(dá)式的求值順序并不確定,表達(dá)式的值可能是32也可能是30。正確的做法是分割這些子表達(dá)式為獨(dú)立的表達(dá)式。 3、應(yīng)避免將多個(gè)包含該運(yùn)算符的表達(dá)式用于實(shí)參。在調(diào)用函數(shù)時(shí),實(shí)參的求值順序標(biāo)準(zhǔn)C并沒(méi)有明確規(guī)定。 printf("%d,%d",++i,i++); 此函數(shù)的輸出值是不確定的,與編譯器有關(guān)。 4、前綴自增、自減運(yùn)算符的優(yōu)先級(jí)和一元的正號(hào)、負(fù)號(hào)優(yōu)先級(jí)相同,且是右結(jié)合的。 后綴自增、自減運(yùn)算符的優(yōu)先級(jí)比一元的正號(hào)、負(fù)號(hào)的優(yōu)先級(jí)高,且是左結(jié)合的。 - --i;相當(dāng)于-(--i); -i--;相當(dāng)于-(i--); sizeof運(yùn)算符 sizeof的使用注意以下幾點(diǎn): 1、sizeof可以用于數(shù)據(jù)類型和表達(dá)式(用于表達(dá)式時(shí)可以沒(méi)有括號(hào)), 不可以用于函數(shù)類型、不完全類型或位字段。 2、sizeof的優(yōu)先級(jí)為2級(jí),比算術(shù)運(yùn)算符的優(yōu)先級(jí)高, 如果采用不帶括號(hào)形式的使用方法要特別注意。 3、表達(dá)式進(jìn)行sizeof運(yùn)算后的結(jié)果就是該表達(dá)式值的類型值。運(yùn)算結(jié)果在程序編譯時(shí)決定。 int i;sizeof(i+1); 等價(jià)于 sizeof(int); 類型轉(zhuǎn)換 C語(yǔ)言中的類型轉(zhuǎn)換分為兩種:自動(dòng)類型轉(zhuǎn)換和強(qiáng)制類型轉(zhuǎn)換。 以下幾種情況會(huì)發(fā)生自動(dòng)類型轉(zhuǎn)換: 1 算術(shù)表達(dá)式或邏輯表達(dá)式中操作數(shù)的類型不相同,此轉(zhuǎn)化稱為算術(shù)轉(zhuǎn)換; 2 賦值運(yùn)算符右側(cè)表達(dá)式類型和左側(cè)的變量不匹配; 3 函數(shù)調(diào)用中的實(shí)參和形參類型不匹配; 4 return語(yǔ)句中表達(dá)式類型和函數(shù)返回值類型不匹配。 算術(shù)轉(zhuǎn)換多用于二元運(yùn)算符的運(yùn)算對(duì)象上,包括算術(shù)運(yùn)算符和關(guān)系運(yùn)算符。 一般都是提升的,不會(huì)產(chǎn)生數(shù)據(jù)丟失; 賦值中的轉(zhuǎn)換原則:把賦值運(yùn)算符右側(cè)表達(dá)式的類型轉(zhuǎn)換為左側(cè)變量的類型, 此轉(zhuǎn)換有時(shí)是提升的有時(shí)是截?cái)嗟模?/div> return類型與函數(shù)返回值類型不匹配時(shí)有時(shí)會(huì)轉(zhuǎn)化為返回值類型, 有時(shí)程序無(wú)法通過(guò)編譯,所以強(qiáng)烈建議return語(yǔ)句表達(dá)式類型與返回值類型一致; 實(shí)參和形參類型不匹配時(shí)要么是引起精度損失,要么是編譯出錯(cuò), 建議大家在使用函數(shù)時(shí),要遵守參數(shù)列表中對(duì)應(yīng)的實(shí)參與形參類型應(yīng)當(dāng)相同的原則。 使用強(qiáng)制類型轉(zhuǎn)換符注意幾點(diǎn): 1 類型轉(zhuǎn)換運(yùn)算符為一元運(yùn)算符,優(yōu)先級(jí)高于二元運(yùn)算符; 2 強(qiáng)制類型轉(zhuǎn)換運(yùn)算只對(duì)其后緊跟著的變量有效。 int f+d; 已知f為float型,d為double型,這樣操作后只會(huì)將f轉(zhuǎn)換為int型。如果想讓f+d的結(jié)果轉(zhuǎn)換為為int型,應(yīng)該 int(f+d); 3 強(qiáng)制類型轉(zhuǎn)換只是改變了某一表達(dá)式中變量的類型, 而不是真正改變了變量的類型,后面遇到此變量參與運(yùn)算時(shí),它的類型依然是原來(lái)的。 數(shù)組的定義及初始化 在C語(yǔ)言中,一維數(shù)組的定義方式如下: 類型說(shuō)明符 數(shù)組名[常量表達(dá)式]; 其中,類型說(shuō)明符用來(lái)說(shuō)明數(shù)組元素的類型;數(shù)組名是用戶自定義的標(biāo)識(shí)符; 常量表達(dá)式中不能含有變量,因?yàn)閿?shù)組一旦被定義,它的大小就已經(jīng)被劃定,無(wú)法動(dòng)態(tài)的改變, 所以數(shù)組的長(zhǎng)度也就不能是一個(gè)變量。 一維數(shù)組的初始化方式有以下幾種: 1、定義數(shù)組時(shí)就給數(shù)組中的每個(gè)元素賦初值,可以將數(shù)組中元素的值用一個(gè)大括號(hào)括起來(lái), 每個(gè)元素之間用逗號(hào)隔開(kāi)。 int a[8]={34,25,18,99,5,18,60,1}; 也可以只給部分元素賦值。 int a[8]={34,25,18}; 上述語(yǔ)句僅僅對(duì)數(shù)組中的前3個(gè)元素進(jìn)行了賦值,后面剩余的元素則默認(rèn)為0。 2、在聲明數(shù)組時(shí)若對(duì)其中全部元素均賦初值,也可以不指定數(shù)組的具體長(zhǎng)度, 編譯器會(huì)根據(jù)賦值的情況為數(shù)組自動(dòng)指定合適的長(zhǎng)度。 int a[]={34,25,18,99,5,18,60,1}; 編譯器會(huì)默認(rèn)為數(shù)組的長(zhǎng)度為8。 二維數(shù)組的定義: 類型說(shuō)明符 數(shù)組名[常量表達(dá)式1][常量表達(dá)式2]; 二維數(shù)組初始化: 1、直接將二維數(shù)組中的所有元素按照其實(shí)際排列順序進(jìn)行賦值; int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; 這種初始化方法的可讀性很差,因?yàn)閿?shù)組之間的行列關(guān)系非常模糊。 2、將二維數(shù)組的每行分別用大括號(hào)括起來(lái),然后分行給二維數(shù)組賦值; int a[3][4]={{0,1,2,3} {4,5,6,7} {8,9,10,11}}; 3、可以選擇性的對(duì)部分?jǐn)?shù)組元素進(jìn)行賦值; int a[3][4]={{1}{4}}; 上面的語(yǔ)句只對(duì)每行首列進(jìn)行賦值,其它元素默認(rèn)賦值為0。這種初始化方式適合容量比較大的數(shù)組。 4、如果在初始化時(shí)對(duì)二維數(shù)組里的全部元素進(jìn)行賦值,則可以省略第一維的長(zhǎng)度,但是第二維的長(zhǎng)度不能省略。 int a[][3]={0,1,2,3,4,5,6,7,8,9,10,11}; 字符數(shù)組初始化 字符數(shù)組只是數(shù)組的一種特殊類型,因此初始化字符數(shù)組的方法和普通數(shù)組相同。 字符數(shù)組還有其他的方法來(lái)初始化:可以將整個(gè)字符串用雙引號(hào)括起來(lái)再放到大括號(hào)中。 char str[] = {"Good Luck!"}; 大括號(hào)也可以被省略。 char str[] = "Good Luck!"; 越界訪問(wèn) C語(yǔ)言不提供對(duì)于數(shù)組邊界檢查,因此在引用數(shù)組元素時(shí)小心訪問(wèn)越界。 一旦越界,后果不堪設(shè)想! void main() { int a[5] = {1,2,3,4,5}; int b[5] = {6,7,8,9,10}; printf("%d\n",b[6]); } 程序的運(yùn)行結(jié)果是2。盡管程序沒(méi)有崩潰但是發(fā)生了邏輯錯(cuò)誤。如果非法位置上的值是比較敏感的,后果是非常嚴(yán)重的,在程序設(shè)計(jì)使應(yīng)該杜絕這種情況的發(fā)生。 scanf函數(shù) scanf函數(shù)的一般形式是: scanf(格式控制字符串”,地址列表); scanf("%d %d %d",&a,&b,&c); 使用此函數(shù)要注意一下兩點(diǎn): 1、如果輸入空格則認(rèn)為輸入字符串結(jié)束,空格后的字符將作為下一個(gè)輸入項(xiàng); 2、如果輸入的數(shù)據(jù)是double型,要在類型前面加字符'l'做修飾符。 double f; scanf("%f",&f); 改為 scanf("%lf",&f); 宏 宏定義又稱為宏代換、宏替換,簡(jiǎn)稱“宏”, 使用宏可提高程序的通用性和易讀性,減少不一致性,減少輸入錯(cuò)誤和便于修改。 使用宏要注意以下問(wèn)題: 1、宏名一般用大寫(xiě); 2、宏定義末尾不加分號(hào); 3、宏定義寫(xiě)在函數(shù)的花括號(hào)外邊,作用域?yàn)槠浜蟮某绦?,通常在文件的最開(kāi)頭??梢杂?undef命令終止宏定義的作用域; 4、宏定義允許嵌套; #define WIDTH 80 #define LENGTH (WIDTH+40) 5、函數(shù)調(diào)用在編譯后程序運(yùn)行時(shí)進(jìn)行,并且分配內(nèi)存。 宏替換在編譯前進(jìn)行,不分配內(nèi)存。 const只讀變量修飾符 const用來(lái)修飾變量而非常量,但是變量的值不可以修改,使用const在一定程度上可以提高程序的安全性和可靠性。 const變量有兩種定義方式: 1、const在類型的前面 const int var =100; 2、const在類型的后面 int const var =100; 兩種定義的方式?jīng)]有本質(zhì)區(qū)別。 數(shù)組與指針 指向數(shù)組的指針與數(shù)組名 指向數(shù)組的指針指向數(shù)組的首元素,即指針變量保存數(shù)組首地址。 數(shù)組名有兩重意思: 1、數(shù)組的名稱; 2、&a[0]也就是數(shù)組的首地址 數(shù)組名不是指針。 字符指針與字符數(shù)組比較 1、賦值方式不同:對(duì)字符數(shù)組進(jìn)行賦值時(shí),不可以用整個(gè)字符串進(jìn)行賦值,只能對(duì)其中的某個(gè)字符賦值,下面的賦值方式是錯(cuò)誤的, char str[12];str = "Good Luck!"; 但是對(duì)于字符指針變量來(lái)說(shuō),卻可以采用下面的賦值方式,相當(dāng)于指針str指向一個(gè)字符串常量。 char *str;str="Good Luck!"; 2、地址是否可以改變:指向字符數(shù)組的字符指針和字符數(shù)組名都表示數(shù)組的首地址, 但是字符指針可以通過(guò)一定的計(jì)算(自增或者自減)來(lái)改變自身的指向,而字符數(shù)組名卻不可以。 3、在定義一個(gè)字符數(shù)組時(shí),編譯器就為其分配內(nèi)存單元。而定義一個(gè)字符指針變量時(shí), 編譯器給指針變量分配內(nèi)存單元,但并不知道該指針變量具體指向哪個(gè)字符串,即指針變量存放的地址不確定。 字符串與字符數(shù)組 字符串是常量,存儲(chǔ)在程序的常量區(qū),字符串中的字符不能修改,任何試圖修改字符串中字符的操作都會(huì)引起運(yùn)行時(shí)錯(cuò)誤; 字符數(shù)組是變量,字符數(shù)組中的字符可以修改。 野指針 “野指針”不是NULL指針,是指向“垃圾”內(nèi)存(不可用內(nèi)存)的指針。 人們一般不會(huì)錯(cuò)用NULL指針,因?yàn)橛胕f語(yǔ)句很容易判斷。 但是“野指針”是很危險(xiǎn)的,if無(wú)法判斷一個(gè)指針是正常指針還是“野指針”。 有個(gè)良好的編程習(xí)慣是避免“野指針”的唯一方法。 野指針的成因主要有三種: 1、指針變量沒(méi)有被初始化。 2、指針被free或者delete之后沒(méi)有置為NULL,讓人誤以為該指針是個(gè)合法的指針而繼續(xù)使用。 3、指針操作超越了變量的作用范圍。比如返回指向棧內(nèi)存的指針,由于棧內(nèi)存在函數(shù)結(jié)束時(shí)會(huì)被釋放,此時(shí)使用該指針就會(huì)產(chǎn)生意想不到的后果。 函數(shù)指針 函數(shù)指針是指向函數(shù)的指針變量。函數(shù)指針的聲明方法: 函數(shù)類型 (*指針變量名) (); 指向函數(shù)的指針變量所指向的地址其實(shí)就是函數(shù)中第一條指令的地址。 調(diào)用該函數(shù)時(shí)除了通過(guò)函數(shù)名來(lái)調(diào)用它以外,還可以通過(guò)指向該函數(shù)的指針變量來(lái)調(diào)用。 有一點(diǎn)要注意:一個(gè)指向函數(shù)的指針其初始值不能為空,因?yàn)樗谑褂弥氨仨毐毁x予一個(gè)真實(shí)的函數(shù)地址。 結(jié)構(gòu)體 結(jié)構(gòu)體變量的定義有三種形式: 1、先聲明結(jié)構(gòu)體類型再定義結(jié)構(gòu)體變量; struct 結(jié)構(gòu)體類型名 { 數(shù)據(jù)類型名1 成員名1; 數(shù)據(jù)類型名2 成員名2; …… …… 數(shù)據(jù)類型名n 成員名n; }; struct 結(jié)構(gòu)體類型名 結(jié)構(gòu)體變量名; 2、聲明類型的同時(shí)定義變量; struct 結(jié)構(gòu)體類型名 { 數(shù)據(jù)類型名1 成員名1; 數(shù)據(jù)類型名2 成員名2; …… …… 數(shù)據(jù)類型名n 成員名n; }變量名列表; 3.直接定義結(jié)構(gòu)體變量而沒(méi)有結(jié)構(gòu)體類型名。 struct { 數(shù)據(jù)類型名1 成員名1; 數(shù)據(jù)類型名2 成員名2; …… …… 數(shù)據(jù)類型名n 成員名n; }變量名列表; 結(jié)構(gòu)體變量的初始化 在定義結(jié)構(gòu)體變量時(shí)就可以對(duì)其進(jìn)行初始化,若沒(méi)有初始化,編譯器會(huì)給每個(gè)成員一個(gè)默認(rèn)值。 位域 位域是把一個(gè)字節(jié)的二進(jìn)制位劃分為不同的區(qū)域,并說(shuō)明每個(gè)區(qū)域的位數(shù)。 位域從本質(zhì)上說(shuō)就是一種結(jié)構(gòu)類型,不過(guò)其成員是按二進(jìn)制位分配的,所以位域的使用和結(jié)構(gòu)成員的使用相同。 使用位域有以下優(yōu)勢(shì): 1、每個(gè)區(qū)域都有一個(gè)域名允許程序員按域名進(jìn)行操作; 2、使用位域結(jié)構(gòu)類型可以節(jié)省存儲(chǔ)空間。 struct byte_struct { int x:8; int y:2; int z:6; }field; field為byte_struct類型變量,共占用2個(gè)字節(jié)。其中x占8位,y占2位,z占6位。 共用體 結(jié)構(gòu)體在內(nèi)存中采用線性存儲(chǔ),存儲(chǔ)空間大小大于(由于操作系統(tǒng)的字節(jié)對(duì)齊)等于內(nèi)部成員之和; 共用體成員存儲(chǔ)時(shí)采用覆蓋技術(shù),共享存儲(chǔ)空間。 共用體變量所占內(nèi)存長(zhǎng)度等于成員變量中所占存儲(chǔ)空間最大的那個(gè),由于成員被分配在同一段內(nèi)存空間中, 共用體變量的值是最后一次存放成員的值,就是說(shuō)在某一時(shí)刻只有一個(gè)成員變量起作用。 struct { int i; float j; }sum; union { int i; float j; }sum; int型數(shù)據(jù)占4個(gè)字節(jié)的內(nèi)存,float型數(shù)據(jù)占4個(gè)字節(jié)內(nèi)存。結(jié)構(gòu)體變量所占內(nèi)存大小為i和j所占內(nèi)存之和,即8個(gè)字節(jié);共用體變量sum所占內(nèi)存大小為4個(gè)字節(jié)。 內(nèi)存對(duì)齊 內(nèi)存對(duì)齊(或字節(jié)對(duì)齊):內(nèi)存空間里的數(shù)據(jù)按照一定的對(duì)齊規(guī)則在內(nèi)存空間中排列,而不是一個(gè)一個(gè)順序存放。 字節(jié)對(duì)齊的細(xì)節(jié)和具體編譯器實(shí)現(xiàn)相關(guān),但一般而言內(nèi)存對(duì)齊滿足三個(gè)準(zhǔn)則: 1、結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除; 2、結(jié)構(gòu)體每個(gè)成員相對(duì)于結(jié)構(gòu)體首地址的偏移量都是成員大小的整數(shù)倍,如有需要編譯器會(huì)在成員之間加上填充字節(jié); 3、結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要編譯器會(huì)在最末一個(gè)成員之后加上填充字節(jié)。 struct { int a; short b; double f; char c; short d; }stu; void main { int i = 0; i = sizeof(stu); printf("%d\n",i); } 此函數(shù)的輸出結(jié)果是20。 枚舉 如果遇到變量取值能夠列舉的情況,就可以使用枚舉數(shù)據(jù)類型。 枚舉類型的定義形式和結(jié)構(gòu)體和共用體類似. enum 枚舉名{枚舉值表}; 枚舉類型看似構(gòu)造類型,但實(shí)質(zhì)上是一種基本類型,因?yàn)槊杜e元素實(shí)際上是常量,枚舉常量的數(shù)據(jù)類型是int型。 在默認(rèn)情況下枚舉常量的值是在枚舉值列表中的順序號(hào),依次為0、1、2……。 enum colour{ red, //red = 0 green, //green = 1 blue //blue = 2 }; 也可以在定義枚舉類型時(shí)給枚舉常量指定值。 enum colour{ red = 4, green = 7, blue = 1 }; 如果只對(duì)一個(gè)枚舉常量賦值,沒(méi)有給后續(xù)的枚舉常量賦值,那么這些常量會(huì)被賦予后續(xù)的值。 enum colour{ red, green = 20, blue }; 在這個(gè)聲明中,red默認(rèn)為0,對(duì)green賦值為20,那么blue就取20的下一個(gè)值21。 typedef typedef被稱為用戶自定義類型,其實(shí)不是一種用戶定義的新的數(shù)據(jù)類型,只是某種數(shù)據(jù)類型的別名。 使用typedef和#define指令都可以定義自己命名的數(shù)據(jù)類型,不過(guò)二者仍然具有以下幾點(diǎn)區(qū)別: 1、typedef只針對(duì)數(shù)據(jù)類型,不針對(duì)值。#define則即可以針對(duì)數(shù)據(jù)類型也可以針對(duì)值; 2、typedef是對(duì)已有數(shù)據(jù)類型的徹底“封裝”,在聲明之后就不可以再往其中增添任何代碼。 #define只是簡(jiǎn)單的文本替換,定義之后仍然可以增加一些合法的代碼; 3、在定義幾個(gè)連續(xù)的變量聲明中,用typedef定義的變量可以保證所有的變量都為同一數(shù)據(jù)類型,但是#define定義的類型則無(wú)法保證。 typedef char *Pchar; Pchar p1,p2;//p1、p2都為字符指針類型 #define Pchar char* Pchar p1, p2;//p1為字符指針類型,p2為字符型。 |
|