typedef struct ms1
{
char a;
int b;
} MS1;
假設MS1按如下方式內存佈局(本文所有示意圖中的內存地址從左至右遞增):
_____________________________
| | |
| a | b |
| | |
+---------------------------+
Bytes: 1 4
因爲MS1中有最強對齊要求的是b字段(int),所以根據編譯器的對齊規則以及ANSI C標準,MS1對象的首地址一定是4(int類型的對齊模數)的倍數。那麼上述內存佈局中的b字段能滿足int類型的對齊要求嗎?嗯,當然不能。如果你是編譯器,你會如何巧妙安排來滿足CPU的癖好呢?呵呵,經過1毫秒的艱苦思考,你一定得出瞭如下的方案:
_______________________________________
| |///////////| |
| a |//padding//| b |
| |///////////| |
+-------------------------------------+
Bytes: 1 3 4
typedef struct ms2
{
int a;
char b;
} MS2;
或許你認爲MS2比MS1的情況要簡單,它的佈局應該就是
_______________________
| | |
| a | b |
| | |
+---------------------+
Bytes: 4 1
因爲MS2對象同樣要滿足4字節對齊規定,而此時a的地址與結構體的首地址相等,所以它一定也是4字節對齊。嗯,分析得有道理,可是卻不全面。讓我們來考慮一下定義一個MS2類型的數組會出現什麼問題。C標準保證,任何類型(包括自定義結構類型)的數組所佔空間的大小一定等於一個單獨的該類型數據的大小乘以數組元素的個數。換句話說,數組各元素之間不會有空隙。按照上面的方案,一個MS2數組array的佈局就是:
|<- array[1] ->|<- array[2] ->|<- array[3] .....
__________________________________________________________
| | | | |
| a | b | a | b |.............
| | | | |
+----------------------------------------------------------
Bytes: 4 1 4 1
當數組首地址是4字節對齊時,array[1].a也是4字節對齊,可是array[2].a呢?array[3].a ....呢?可見這種方案在定義結構體數組時無法讓數組中所有元素的字段都滿足對齊規定,必須修改成如下形式:
___________________________________
| | |///////////|
| a | b |//padding//|
| | |///////////|
+---------------------------------+
Bytes: 4 1 3
現在無論是定義一個單獨的MS2變量還是MS2數組,均能保證所有元素的所有字段都滿足對齊規定。那麼sizeof(MS2)仍然是8,而a的偏移爲0,b的偏移是4。
typedef struct ms3
{
char a;
short b;
double c;
} MS3;
我想你一定能得出如下正確的佈局圖:
padding
|
_____v_________________________________
| |/| |/////////| |
| a |/| b |/padding/| c |
| |/| |/////////| |
+-------------------------------------+
Bytes: 1 1 2 4 8
sizeof(short)等於2,b字段應從偶數地址開始,所以a的後面填充一個字節,而sizeof(double)等於8,c字段要從8倍數地址開始,前面的a、b字段加上填充字節已經有4 bytes,所以b後面再填充4個字節就可以保證c字段的對齊要求了。sizeof(MS3)等於16,b的偏移是2,c的偏移是8。接着看看結構體中字段還是結構類型的情況:
typedef struct ms4
{
char a;
MS3 b;
} MS4;
MS3中內存要求最嚴格的字段是c,那麼MS3類型數據的對齊模數就與double的一致(爲8),a字段後面應填充7個字節,因此MS4的佈局應該是:
_______________________________________
| |///////////| |
| a |//padding//| b |
| |///////////| |
+-------------------------------------+
Bytes: 1 7 16