資料結構記憶體邊界對齊的三條原則

2021-05-22 06:21:47 字數 2590 閱讀 8752

struct example1 ;

struct example2 ;

#pragma  pack()

在 原來那篇日誌中,通過寫程式測試發現規律後,便推測上述的strurct example2的結構大小應該是24個位元組,但ygone網友在vs2008上得到的結果是16個位元組,自己這才寫程式在vc6.0, vs2008, gcc上測試,得到的結果都是16個位元組。

struct example2資料結構的大小是16個位元組,這個值是這樣計算出來的:

1(char c) + 3(padding) + 8(struct example1 e) + 2(short s) + 2(padding) = 16。

struct example1的大小是8位元組,這個非常明顯。

為什麼struct example2的大小要如此計算呢?通過學習,總結出資料結構記憶體邊界對齊的三條原則,如下:

原 則一:記憶體邊界對齊是為了簡化cpu和記憶體之間的介面設計,提高記憶體讀寫的效率。每一種原子資料在儲存時都有兩個屬性:它的起始位址約束和它本身的大小。 在windows下,可以使用__alignof(type)來檢視type型別的起始位址約束,char是1,short是2,int是4, double是8等等。在linux下,char是1,short是2,其他都是4。

原則二:對於非原子型別的組合型別,比如struct, union, class等,它的起始位址約束必須能夠滿足它的所有資料成員的起始位址約束。即,整體必須照顧到每乙個組成部分。

原則三:對於乙個組合型別s,分配乙個s型別的陣列,則s中每個s物件都必須滿足s的起始位址約束。原則三的結果是,乙個組合型別,很有可能為了滿足它自身的起始位址約束而在它的後面填充一些位元組。

現在來看為什麼struct example2的大小應該那樣計算:

sizeof(struct example2) = sizeof(char) + padding_c_e + sizeof(struct example1) + padding_e_s + sizeof(short) + padding_end

先要計算struct example1的大小:

sizeof(struct example1) = sizeof(short) + padding_a_b + sizeof(long) + padding_end

alignof(short) = 2, alignof(long) = 4,所以short a之後必須填充兩個位元組才能保證long b的起始位址是4的整數倍,所以padding_a_b = 2。

那 麼alignof(struct example1)是多少呢?根據原則二,alignof(struct example1)必須滿足成員a和b的對齊約束。假設struct example1物件的起始位址是x,x必須是2的整數倍以保證成員a能對齊,同時x+offset(b) = x+4必須是4的整數倍以保證成員b能對齊,要使x+4是4的整數倍,x也必須是4的整數倍,所以align(struct example1) = 4。現在:

sizeof(struct example1) = 2 + 2 + 4 + padding_end = 8 + padding_end,因為alignof(struct example1) = 4,所以末尾不需要填充,因此:

sizeof(struct example1) = 2 + 2 + 4 = 8。

現在計算struct example2的大小:

sizeof(struct example2) = sizeof(char) + padding_c_e + sizeof(struct example1) + padding_e_s + sizeof(short) + padding_end

= 1 + padding_c_e  + 8 + padding_e_s + 2 + padding_end

因為alignof(struct example1) = 4,所以padding_c_e = 3,這樣1+3為4的整數倍。

因為alignof(short) = 2,而1+3+8就是2的整數倍,所以padding_e_s = 0

根據計算alignof(struct example1)的過程,可以計算出alignof(struct example2) = 4,而1 + 3 + 8 + 2 = 14,不是4的整數倍,所以padding_end = 2。

最終:sizeof(struct example2) = 1 + 3 + 8 + 0 + 2 + 2 = 16

如果使用的#pragma pack(2)結果又怎麼樣呢?

此 時,在struct example1中,alignof(long)=4,但是因為#pragma pack(2),所以long b的偏移量不需要填充就能滿足2位元組對齊的要求,所以sizeof(struct example1) = 2 + 4 = 6, alignof(struct example1) = 2

所以sizeof(struct example2) = sizeof(char)  + padding_c_e + sizeof(struct example1) + padding_e_s + sizeof(short) + padding_end

資料結構對齊原則

一種資料結構 c語言中聚合資料型別的一類 可以被宣告為變數 陣列 指標等,用以實現比較複雜的資料結構 是一系列元素的集合,這些元素被稱為結構體成員 結構體成員需要用結構體名訪問。struct as1 s1是結構體變數 一般情況下,宣告出現三個部分的兩個部分即可 標誌或者變數可省略 結構體可以包含其他...

我寫blog的三條原則

關於隱私。隱私是不被別人知曉的權利。我可以決定選擇寫或不寫任何關於我自己的資訊 我的 號碼,我的郵件,我的行蹤,我的想法 只要我願意 但是我沒有有權利在未經別人允許的情況下把別人的資訊發布出來。關於頻度。一天一篇是結果,不是目標。寫得有規律,看的人就多些,寫得少沒問題,但是不要奇怪為什麼沒有人看了。...

C 結構體的記憶體對齊原則

什麼是結構體?結構體也是一種資料型別,但不是基本資料型別 如int floatc中內建的型別 而是一種聚合 aggregate 型別,它的成員是基本資料型別或其它已定義的型別或自身型別的指標。對結構體的基本概念有了大概認識後,就要進一步了解它在記憶體中的實現,而結構體的記憶體實現與記憶體對齊原則相關...