概念
- 一種數據結構;
- C語言中聚合數據類型的一類;
- 可以被聲明為變量、數組、指針等,用以實現比較復雜的數據結構;
- 是一系列元素的集合,這些元素被稱為結構體成員;
- 結構體成員需要用結構體名訪問。
結構體聲明
struct A{ //struct是關鍵字, A是結構體標志
int a; //a,b是結構體成員列表
char b;
}s1; //s1是結構體變量
注意事項:
- 一般情況下,聲明出現三個部分的兩個部分即可(標志或者變量可省略)
- 結構體可以包含其他結構體,也可以包含指向自己的指針
- 結構體互相包含時,需要對其中一個進行不完整聲明
結構體對齊規則
- 計算結構體大小不是元素單純相加;
- 32位CPU取四個字節比一個字節更高效方便;
- 若每個元素首地址都是4的整數倍,取數據元素就能更高效方便;
- 每個特定平台上編譯器都有自己的默認的對齊系數(對齊模數),可通過編譯命令來改變這一系數;
#pragma pack(n);//n=1,2,4,8,16
,其中n就是你想要指定的系數。- 一般情況下32位默認4字節對齊。
對齊原因
-
平台原因(移植原因)
不是所有的硬件平台都能訪問任意地址的任意數據,某些硬件平台只能在某些地址處取某些特定類型的數據的,否則拋出硬件異常。 -
性能原因
數據結構(尤其是棧),應該盡可能在自然邊界上對齊,因為在訪問為對齊的內存時,處理器需要訪問兩次,而對齊的內存處理器只需要訪問一次。
對齊規則
- 第一個成員在與結構體變量偏移量(offset)為0的地址處。
- 其他成員變量要對齊到對齊數的整數倍的地址處。
- 對齊數 = 對齊系數 與 該成員大小的較小值。
#pragma pack(n);
中的n就是對齊系數。- VS中默認的值為8;linux中的默認值為4。
- 結構體總大小為最大對齊數(每個成員變量除了第一個成員都有一個對齊數)的整數倍。
- 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。
舉例說明對齊原則
1.下面的結構體大小分別是多大(假設32位機器)?
struct A {
char a; //1
char b; //1
char c; //1
};
//進行整體對齊,最大類型為1<對齊系數4,按1整體對齊,所以1+1+1=3
struct B {
int a; //4
char b; //1
short c;//2
};
//進行整體對齊,最大類型為4=對齊系數4,所以按4整體對齊4 1+2=3<4 對齊4 所以4+4=8
struct C {
char b; //1
int a; //4
short c;//2
};
//進行整體對齊,最大類型為4=對齊系數4,所以按4整體對齊 1<4(對齊4) 4=4 2<4(對齊4) 所以4+4+4=12
#pragma pack(2)
struct D {
char b; //1
int a; //4
short c;//2
};
//進行整體對齊,最大類型為4>對齊系數n(2),所以按2整體對齊 1<2(對齊2)4>2(2的倍數) 2=2 所以2+4+2=8
答案及解析:3 8 12 8
2. 有一個如下的結構體:
struct A{
long a1;
short a2;
int a3;
int *a4;
};
請問在64位編譯器下用sizeof(struct A)計算出的大小是多少?
24
28
16
18
答案及解析:24
64位編譯器下:指針8字節(一定不能忘記),題目不說默認4字節對齊
long a1; //8
short a2; //2 8+2=10(不是4的倍數)對齊到4的倍數12
int a3; //4 4+12=16(4的倍數)
int *a4; //8 8+16=24(4的倍數)
3.在32位cpu上選擇缺省對齊的情況下,有如下結構體定義:
struct A{
unsigned a : 19;
unsigned b : 11;
unsigned c : 4;
unsigned d : 29;
char index;
};
則sizeof(struct A)的值為()
9
12
16
20
答案及解析16
題目不說,默認4字節對齊
19+11=30<32bit 4
4+29=33>32bit 4+4
1byte=8bit 1 對齊到 4
4+4+4+4=16
C++中的結構體struct---類
- 在C++中struct是對於C語言中struct的擴展,因為C++是面向對象的語言,可以描述對象的行為,所以在C++中struct內可以放函數,從而就具有類的功能,但又和class有一定的區別。
class和struct的區別
- class默認成員是私有的private,struct默認成員是公有的public
- class繼承默認是私有的private,struct繼承默認是公有的public
- C++中結構體可以不要struct關鍵字,C語言中除了typedef定義別名之外是必須要struct關鍵字。