【转】彻底搞清计算结构体大小和数据对齐原则
生活随笔
收集整理的這篇文章主要介紹了
【转】彻底搞清计算结构体大小和数据对齐原则
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
數(shù)據(jù)對齊:
許多計算機系統(tǒng)對基本數(shù)據(jù)類型合法地址做出了一些限制,要求某種類型對象的地址必須是 某個值K(通常是2,4或8)的倍數(shù)。這種對齊限制簡化了形成處理器和存儲器系統(tǒng)之間的接口的硬件 設計。例如,假設一個處理器總是從存儲器中取出8個字節(jié),則地址必須為8的倍數(shù)。如果我們能保 證將所有的double類型數(shù)據(jù)的地址對齊成8的倍數(shù),那么就可以用一個存儲器操作來讀或者寫值了。 否則,我們可能需要執(zhí)行兩次存儲器訪問,因為對象可能被分放在兩個8字節(jié)存儲塊中。 當數(shù)據(jù)類型為結構體時,編譯器可能需要在結構體字段的分配中插入間隙,以保證每個結構元素都 ? ? ? ? ?滿足它的對齊要求。而結構本身對它的地址也有一些對齊要求,此時可能需要在結構末尾填充一些 ? ? ? ? ?空間,以滿足結構體整體的對齊----向結構體元素中最大的元素對齊。稍后會用代碼說明!!! ? ? ? ? ? ? ? ? ?Linux和Microsoft Windows的對齊方式有何不同: ? ? ? ? ? ? ? ?一.Linux的對齊策略: 在Linux中2字節(jié)數(shù)據(jù)類型(例如short)的地址必須是2的倍數(shù),而較大的數(shù)據(jù)類型(例如int,int * ,float和double)的地址必須是4的倍數(shù)。也就是說Linux下要么2字節(jié)對齊,要么4字節(jié)對齊,沒 有其他格式的對齊。 ? ? ? ? ? ? ? 二.Microsoft Windows的對齊策略: 在Windows中對齊要求更嚴--任何K字節(jié)基本對象的地址都必須是K的倍數(shù),K=2,4,或者8. 特別地,double或者long long類型數(shù)據(jù)的地址應該是8的倍數(shù)。可以看出Windows的對齊策略和 Linux還是不同的。稍后用代碼說明!!! ?接下來用代碼和圖文說明兩者的對齊方式(不同的對齊方式產生的結構體大小不同): 測試代碼如下: / // filename:DataAlignment / #include<stdio.h> typedef struct { char c; int i[2]; double v; }S; int main() { printf("size of S = %d\n", sizeof(S)); return 0; }?
程序中定義了一個結構體,在沒有任何數(shù)據(jù)對齊時內存布局如下: 一.在紅帽Linux i686上編譯編譯后結構S的布局如下: ? ? ? ? ? ? ? ?? 由于要保證結構體每個元素都要數(shù)據(jù)對齊,因此必須在c和i[0]之間插入3字節(jié)的間隙(圖中陰影部分為編譯器插入的間隙) 使得i[0]和后面的元素的的偏移量都為4的倍數(shù),這樣最終S結構大小為20字節(jié)。 運行程序結果為: ?size of S = 20 ? ? ? ? ? ? 二.在Microsoft Windows 上編譯后S的內存布局如下: 在windows下int類型4個字節(jié),因此int類型要向4字節(jié)對齊,double類型8字節(jié),因此要向8字節(jié)對齊。因此在 c和i[0]之間插入3字節(jié)的間隙(圖中陰影部分),使得i[0]的偏移量為4的倍數(shù),同時在i[1]和v之間插入4字節(jié)的間隙, 使得v的偏移量為8的倍數(shù)。這樣最終S結構的大小為24字節(jié)。 運行程序結果為: ?size of S = 24 ? ? ? ? ? 從以上對比可以看出Linux下和windows下的對齊策略是不同的,這就導致在兩個平臺下結構體的大小不同。 ? ? ? ? ? ? ? ? ? ? ?現(xiàn)在考慮如下代碼: ? ? ? ? ? ? ?? #include<stdio.h> typedef struct { int i; int j; char c; }S1; int main() { printf("size of S1 = %d\n", sizeof(S1)); return 0; }?
可能很多人認為編譯后運行結果為9,以為結構體的每個元素都滿足各自的對齊要求。其實不然,別忘了還有要考慮 結構體整體的對齊。假如有如下聲明: S1 ?d[4]; 如果這樣分配9個字節(jié),不可能滿足d的每個元素的對齊要求,因為這些元素的地址分別為xd,xd+9,xd+18, xd+27。這樣只有第一個元素滿足4字節(jié)對齊的要求,而其他的元素的地址都不是4的倍數(shù)。因此編譯器會在結構體的末尾填充3字節(jié)滿足結構體整體的對齊要求,填充后的內存布局如下: 這樣一來,d的元素的地址分別為xd,xd+12,xd+24,xd+36,滿足4字節(jié)的整數(shù)倍,這樣最終S1的大小 為12字節(jié),而不是9字節(jié).
總結:通過代碼的對比,可以看出Linx和Windwos的數(shù)據(jù)對齊有所差異,這就導致 在一些情況下兩者平臺結構體類型大小的不同。通過以上示例分析我們可以很簡單的 計算出在任何平臺下結構體的大小。讀者可以找相關的練習題繼續(xù)練習下,驗證結果 的正確性。相信仔細閱讀本文應該能搞定所有類似的問題!!! 原文地址:http://blog.csdn.net/qianghaohao/article/details/51011418
總結
以上是生活随笔為你收集整理的【转】彻底搞清计算结构体大小和数据对齐原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uniapp 让支付触手可及,封装了微信
- 下一篇: 国标28181: 视频国标28181协议