結構體字節對齊准則:
1. 結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;
2. 結構體每個成員相對於結構體首地址的偏移量都是當前成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節;
3. 結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之后加上填充字節。
4. 在嵌套結構中需要把內部‘打散'后再進行對齊計算。
// sizeof(結構體).cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include<iostream> using namespace std; struct A { char a; int b; }; struct B { char a; A a1; char b; }; int _tmain(int argc, _TCHAR* argv[]) { cout<<sizeof(A)<<endl<<sizeof(B); return 0; }
上述程序的輸出結果是8和16.
下面結合前面給出的准則具體分析一下。
對於結構體A其基本成員類型有char和int兩種,最寬的是int占用4個字節,那么根據准則1,編譯器會自動為結果體A分配一個能被4整除的首地址,A的第一個成員char的首地址就是結構體A的首地址,即偏移量為0,接下來,下一個成員變量int首地址,如果不做處理的話,應該是相對於A的偏移量是1,這就不滿足准則2了,所以編譯器開始在char的后面填充3個字節,使得int相對於A的偏移量是4,來滿足准則2,然后結構體的總大小就是1(char)+3(填充)+4(int)=8,同時滿足了准則3,不用再填充了,所以sizeof(A)=8。
對於結構體B,其中包括了一個復合類型,查看基本類型的時候,要將其中的結構體A拆分成char和int兩種類型來看,所以結構體B中的基本數據類型是char,char,int,char,最寬的數據類型是int,編譯器會自動為B分配一個能被4整除的首地址,B的第一個成員char的首地址就是結構體B的首地址,即偏移量為0,接下來,下一個成員變量A的首地址,如果不做處理的話,應該是相對於B的偏移量是1,這就不滿足准則2了,所以編譯器開始在char的后面填充3個字節,使得成員A相對於所在結構體B的地址偏移量是4,來滿足准則2,這時加上B的長度8,B中最后一個成員char相對於B來說地址偏移量是8,能滿足准則2,所以不需要在A的后面填充字節,這時B的總長度是1(char)+3(填充)+8(A)+1(char)=13,不滿足准則3,所以還需要在最后一個char后面再添加3個字節,最后得到B的總大小是1(char)+3(填充)+8(A)+1(char)+3(填充)=16,所以sizeof(B)=16。
結構體技巧:結構體支持整體賦值,因此可以利用結構體來處理數組的整體賦值操作。