記憶體對齊規則之我見

2021-08-22 08:29:47 字數 2397 閱讀 7330

2023年03月23日 星期四, 發表於 武漢

如果你對本文有任何的建議或者疑問, 可以在 這裡給我提 issues, 謝謝! :)

記憶體對齊的原因和理由就不多說了,主要是為了效能和平台移植等因素,編譯器對資料結構進行了記憶體對齊

考慮下面的例項:

123

4567

891011

1213

1415

1617

18

#includeusing namespace std;

struct a;

struct b;

int main()ubuf;

int aa; //佔4位元組空間,當前偏移量已補齊為20

double dou; //佔8位元組空間

}bu;

sizeof(bu) = 4 + 13 + 3(補齊) + 4 + 8 = 32,分析方法類似,在計算aa的偏移量時,我們可以肯定的是一定是int型別的整數倍,由於不作任何緩衝補齊的情況下,number + buffer = 17位元組,為了符合規則1,需要填充3個位元組。

結構體bu稍微變換下aa和dou成員順序,則結果就大不相同:

123

4567

891011

struct bc

ubuf;

double dou; //佔8位元組空間,當前偏移量已補齊為24

int aa; //佔4位元組空間,當前占用空間36位元組,最大double型別,還需要根據規則2補齊

}bu;

此時sizeof(bc) = 4 + 13 + 7(規則1補齊) + 8 + 4 + 4(規則2補齊) = 40 (8的整數倍)

我們可能對於結構體類包含union型別成員抱有疑慮,再考慮下面例項:

123

4567

89

struct bd

ubuf;

}bc;

執行結果是sizeof(bd) = 2 + 2 + 13 +3 = 20,可能你會問,為什麼不是2+13+1 = 16,這是因為union型別比較特殊,計算union成員的偏移量時,需要根據union內部最大成員型別來進行緩衝補齊,所以為了保證偏移量為union最大成員int型別的整數倍,需要在number(short型別)後面填充2個位元組,前面例子中number是int型別,就沒有這個必要了。

再比如:

123

4567

89

struct be

ubuf;

}bc;

它的執行結果是sizeof(be) = 2 + 6 + 13 + 3 = 24,number後面為了與double型別進行對齊而補齊了6個位元組,最後再按照規則2補齊了3個位元組

考慮規則3:

舉個例子,在#pragma pack(1)時,以1個位元組對齊時,屬於最簡單的情況,結構體大小是所有成員的型別大小的和。所以sizeof(bu) = sizeof(bc) = 29,這時與成員變數順序不再相關。其他指定的位元組對齊也很好分析。一般而言,奇數個位元組對齊沒有意義,正常情況下,編碼人員不關心編譯器對記憶體對齊所作的工作。

上面的例子都想明白之後,記憶體對齊的規則應該了然於胸了。 :)

ps: c語言中offsetof()函式可用於檢視特定的結構體成員在結構體中的偏移量,程式設計時可以用於驗證上面的說法。其實現類似如下:

1
#define offsetof(type, member) (size_t)&(((type *)0)->member)

原理是,強制將結構體(型別為type)的起始位址置為0,然後輸出其成員的位址,該位址的大小就是成員在結構體中的偏移量。

規則之外的例子

c99中定義了柔性陣列機制,因此對於乙個結構體,如果最後乙個成員是陣列的話,結構體大小與該成員是否是柔性陣列有密切關係。

123

45

struct sds;

當結構體定義中,最後乙個成員是陣列且陣列大小為0或沒標記時,該成員陣列是柔性陣列,不計入結構體大小,因此sizeof(sds) = 8

而下面的結構體sd的sizeof(sd) = 12,因為最後乙個陣列成員是普通陣列,適用於上述補齊規則。

123

45

struct sds;

我們知道,c++為了相容c,保留了struct關鍵字,但是實際上c++中的struct是乙個預設訪問控制許可權為public的class。c++標準規定:乙個空類的大小為1個位元組,因此在c++中,sizeof(空類或空結構體) = 1,在c語言中,sizeof(空結構體) = 0。

記憶體對齊規則

1 平台原因 移植原因 不是所有的硬體平台都能訪問任意位址上的任意資料的 某些硬 件平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。2 效能原因 資料結構 尤其是棧 應該盡可能地在自然邊界上對齊。原因在於,為了訪問 未對齊的記憶體,處理器需要作兩次記憶體訪問 而對齊的記憶體訪問僅需要一次...

記憶體對齊規則

隔了很久,搞忘了對齊的規則,現在重新複習了下,記下來謹防以後又忘記。1 可以根據 pragma pack 設定對齊係數,且叫為n 2 結構體中,對比每個成員變數自身的大小和n的大小。取小的個為標準,把這個小的叫a吧,稱為按a對齊 3 每個變變數的起始位址需要為a的整數倍,不是整數倍的則補齊。4 最後...

記憶體對齊 記憶體對齊規則解釋 記憶體對齊原理

一 記憶體對齊的原因 我們都知道計算機是以位元組 byte 為單位劃分的,理論上來說cpu是可以訪問任一編號的位元組資料的,我們又知道cpu的定址其實是通過位址匯流排來訪問記憶體的,cpu又分為32位和64位,在32位的cpu一次可以處理4個位元組 byte 的資料,那麼cpu實際定址的步長就是4個...