一、位段
位段:度娘給出的解釋是,c語言允許在乙個結構體中以位為單位來指定其成員所佔記憶體長度,這種以位為單位的成員稱為「位段」或稱「位域」( bit field) 。利用位段能夠用較少的位數儲存資料。
位段的宣告和結構體很相似,但不同的是:
①位段的成員可以是int,unsigned int,signed int,char,short,long,long long(但不能是浮點float,double)型別
②位段的成員名後邊有乙個冒號和乙個數字,這個數字表示位段所佔的二進位制位數。
如:
struct a bitsegement;
那麼位段a多大呢?在計算之前,先說下位段怎麼儲存
簡單說就是看變數後面的數字。先看第乙個變數型別,開闢對應型別大小的位元組,然後數字是多少就佔多少bit,剩餘bit留給下乙個變數用。不夠的話再開闢對應型別大小位元組數。
細說的話,對於位段結構,編譯器會自動進行儲存空間的優化,要遵循這些原則原則:
1)如果乙個位段儲存單元能夠儲存得下位段結構中的所有成員,那麼位段結構中的所有成員只能放在乙個位段儲存單元中,不能放在兩個位段儲存單元中;如果乙個位段儲存單元不能容納下位段結構中的所有成員,那麼從剩餘的位段從下乙個位段儲存單元開始存放。
2)下乙個成員要想使用上乙個成員剩餘的空間,必須和它型別相同,且占用空間不能超出剩餘空間。否則,需單獨占用一塊空間。
3)如果乙個位段結構中只有乙個占有0位的無名位段,則只佔1或0位元組的空間(c語言中是佔0位元組,而c++中佔1位元組);否則其他任何情況下,乙個位段結構所佔的空間至少是乙個位段儲存單元的大小;
3)位段成員儲存也遵循記憶體對齊原則。
再看上面的例子,int型別首先開闢4位元組。_a實際占用25bit,_b實際占用6bit,剩餘1bit不夠_c使用。因此_c申請使用1byte,實際占用7bit,剩餘1bit不夠_d使用。_d需新申請空間。使用位段需注意以下幾點:此時_a,_b,_c共使用9byte,偏移量是9。_d會進行結構體對齊,在偏移量為自己型別大小整數倍的位置開始。因此,_d會在偏移量12的位置開始申請使用4byte,實際占用30bit,剩下2bit仍被浪費了。_e申請使用2byte。
_f進行記憶體對齊,從偏移量20位置開始,申請使用4byte。_g申請2byte。
最後,總占用22byte,但結構體空間大小要是最大對齊數整數倍,所以是24byte。
二、列舉
就是一一枚舉出相類似的東西,如星期,班級,商品等。
enum day // 星期
d1,d2;
enum class//班級
c1,c2;
enum day, enum class都是列舉型別,{}中的是列舉常量,不是變數,不能在程式中用賦值語句再對它賦值。列舉常量它們如果沒有初始化的話,從第乙個預設是0,後面的依次加1。如果初始化了的話,被初始化的列舉常量之前的不變,其他的根據列舉常量的值依次加1。{}後面的d,c類似結構體,是列舉變數。
需要注意的是,可以把列舉常量賦給變數,但不能把列舉常量的數值賦給列舉變數。如d1=mon,d2=tues;是正確的,而d1=0,d2=1;是錯誤的。如果非要把數值賦給列舉變數的話需要通過強制型別轉換,d1=(enum day)0;
#includeint main()
; j = mon;
for (i = 1; i < 32; i++) }
for (i = 1; i < 32; i++)//列印31天內的周一到週日
if (0 == i % 7)
}printf("\n");
}
三、聯合
聯合是一種特殊的自定義型別,這種型別定義的變數包含一系列的成員,特徵是這些成員公用同一塊空間(所以聯合也叫共用體)。
union un
;
因為聯合的成員是共用同一塊記憶體空間的,所以乙個聯合變數的大小,至少是最大成員的大小(因為聯合至少得有能力儲存最大的那個成員)。
當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
int main()
; union un un;
//因為兩個成員占用相同記憶體,所以位址相同
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
un.i = 0x11111111;
//因為char型別是1位元組,16進製表示,char型別只能用2個數字,如果多於2個數字會發生型別截斷
un.c = 0x22;
//輸出286331170,因為共用一塊記憶體且小端儲存,所以本應0x11111111變為0x11111122,十進位制表示286331170
printf("%d\n", un.i);
}
根據上個程式可知,聯合可以判斷當前計算機的大小端儲存。如果計算機是大端儲存,則0x11111111會變為0x22111111,輸出結果是571543825。
自己仿照上例寫個簡單的
int main()u;
u.a = 0x11;
u.b = 0x01;
//小端儲存,結果是1;如果是大端儲存則是16
printf("%d\n", u.a);
}
計算聯合結構的大小
int main()
; union un2
; //下面輸出的結果是什麼?
printf("%d\n", sizeof(union un1));//8
printf("%d\n", sizeof(union un2));//16
}
再算一題
int main()
ip; };
union ip_addr my_ip;
// 176238749轉換為16進製制0xa 81 30 9d,因為是聯合結構
//add和結構體變數ip中的成員共用一塊記憶體,則c1=9d,c2=30,c3=81,c4=a
//十進位制表示為10 129 48 157
my_ip.addr = 176238749;
printf("%d.%d.%d.%d\n", my_ip.ip.c4, my_ip.ip.c3, my_ip.ip.c2, my_ip.ip.c1);
}
位段,列舉,聯合
前面我們說過了自定義型別,包含結構體,位段,列舉,聯合。前一篇我們總結了結構體,今天來說一下位段,列舉,聯合。一 位段 1 位段概念 c語言中允許在乙個結構體中以位為單位來指定其成員所佔記憶體長度,這種以位為單元的成員稱為 位段 或 位域 1 位段的成員可以是int,unsigned int,sig...
位段 列舉 聯合
2.列舉 3.聯合 1.位段的成員必須是 int,unsigned int signed 即必須是整形家族 這是因為位段的成員是以位元位為單位進行儲存的,假如是浮點型別,給成員乙個5.3的容量,0.3的位元位去 找呢?2.位段的成員名後面有乙個冒號和數字 3.具體宣告如下 1.平時我們開闢空間都是偶...
列舉 聯合的講解
列舉顧名思義就是一一枚舉。把可能的取值一一枚舉。列舉型別的定義 enum day enum 以上定義的enum day,enum 都是列舉型別。中的內容是列舉型別的可能取值,也叫列舉常量 這些可能取值都是有值的,預設從0開始,依次遞增1,當然在定義的時候也可以賦初值 例如 enum 列舉的優點 為什...