先介紹三個概念:自身對齊值、指定對齊值、有效對齊值。程序員
自身對齊值:數據類型自己的對齊值,例如char類型的自身對齊值是1,short類型是2;數組
指定對齊值:編譯器或程序員指定的對齊值,32位單片機的指定對齊值默認是4;大數據
有效對齊值:自身對齊值和指定對齊值中較小的那個。spa
對齊有兩個規則:blog
一、不但結構體的成員有有效對齊值,結構體自己也有對齊值,這主要是考慮結構體的數組,對於結構體或者類,要將其補齊爲其有效對齊值的整數倍。結構體的有效對齊值是其最大數據成員的自身對齊值;ci
二、存放成員的起始地址必須是該成員有效對齊值的整數倍。編譯器
舉四個例子編譯
假如結構體起始地址是0x0000,table
成員a的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,佔一個字節;數據類型
成員b的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0001是1的整數倍,故b存放起始地址是0x0001,佔一個字節;
成員c的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0002是1的整數倍,故c存放起始地址是0x0002,佔一個字節;
成員d的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0003是1的整數倍,故d存放起始地址是0x0003,佔一個字節;
此時結構體A的有效對齊值是其最大數據成員的自身對齊值,它的成員都是char類型,故結構體A的有效對齊值是1.
結構體A的存儲結構以下,其中Y是根據規則1補齊的字節,x是規則2補齊的字節。
0x0000 |
0x00001 |
0x0002 |
0x0003 |
a |
b |
c |
d |
根據以上規則能夠知道其餘結構體的存儲結構:
結構體B佔6個字節
0x0000 |
0x00001 |
0x0002 |
0x0003 |
0x0004 |
0x0005 |
a |
x |
b |
b |
c |
d |
結構體C佔12個字節
成員a的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,佔一個字節;
成員b的自身對齊值4,指定對齊值4,因此有效對齊值是4,地址0x0004是4的整數倍,故b存放起始地址是0x0004,佔四個字節;
成員c的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0008是1的整數倍,故c存放起始地址是0x0008,佔一個字節;
成員d的自身對齊值1,指定對齊值4,因此有效對齊值是1,地址0x0009是1的整數倍,故d存放起始地址是0x0009,佔一個字節;
結構體C的成員佔據10個字節,而結構體C的有效對齊值是其成員b的自身對齊值4,10不是4的倍數,故還需補齊兩個字節,此時結構體C佔據12個字節,是4的倍數
以下:
0x0000 |
0x00001 |
0x0002 |
0x0003 |
0x0004 |
0x0005 |
0x0006 |
0x0007 |
0x0008 |
0x0009 |
0x000A |
0x000B |
a |
x |
x |
x |
b |
b |
b |
b |
c |
d |
Y |
Y |
結構體D佔16個字節
0x0000 |
0x00001 |
0x0002 |
0x0003 |
0x0004 |
0x0005 |
0x0006 |
0x0007 |
0x0008 |
0x0009 |
0x000A |
0x000B |
0x000C |
0x000D |
0x000E |
0x000F |
a |
x |
x |
x |
b |
b |
b |
b |
b |
b |
b |
b |
c |
d |
Y |
Y |
代碼驗證以下: