最近研究了一下c語言中結構體大小的計算,根據自己的理解以及參考網上的資料,
想做一點總結。
先介紹一個相關的概念——偏移量。偏移量指的是結構體變量中成員的地址和結構體
變量地址的差。結構體大小等於最後一個成員的偏移量加上最後一個成員的大小。
由於存儲變量時地址對齊的要求,編譯器在編譯程序時會遵循兩條原則:
一、結構體變量中成員的偏移量必須是成員大小的整數倍(0被認為是任何數的整數倍)
二、結構體大小必須是所有成員大小的整數倍。
這是一種說法,還有一種說法:
結構體默認的字節對齊一般滿足三個准則:
1) 結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;
2) 結構體每個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,
如有需要編譯器會在成員之間加上填充字節(internal adding);
3) 結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末
一個成員之後加上填充字節。
我自己寫了三個結構體測試了一下,代碼如下:
輸出結果是:
12
8
20
先看第一個結構體,第一個成員a的偏移量為0。第二個成員b的偏移量是第一個成員的偏移量加上第一個成員的大小(0+4),其值為4;第三個成員c的偏移量是第二個成員的偏移量加上第二個成員的大小(4+1),其值為5。上面的例子中前兩個成員的偏移量都滿足要求,但第三個成員的偏移量為5,並不是自身(int)大小的整數倍。編譯器在處理時會在第二個成員後面補上3個空字節,使得第三個成員的偏移量變成8。結構體大小等於最後一個成員的偏移量加上最後一個成員的大小。偏移量8加上最後一個成員c自身的大小,即為9,9不能被最寬基本類型成員大小整除,所以這裡編譯器會在最後補齊3個字節,得出12。
至於第二個結構體,大小等於最後一個成員的偏移量加上其大小,上面的例子中計算出來的大小為8,滿足要求。
按照上述的計算規則,結構體一和結構體二都可以計算出與輸出一致的結果,可是結構體三有點不明白。
偏移量 填充字節 成員自身大小
0 4
4 1
5 1 2
8 8
16 4