C C 記憶體對齊詳解

2021-06-22 07:13:11 字數 1807 閱讀 1807

如果體系結構是不對齊的,a中的成員將會乙個挨乙個儲存,從而可能出現sizeof(a)為11的情況。如果按照4位元組倍數對齊,這時候sizeof(a)結果是12,顯然對齊更浪費了空間。那麼為什麼要使用對齊呢?體系結構的對齊和不對齊,是在時間和空間上的乙個權衡,對齊可以節省cpu訪問資料的時間。假設乙個體繫結構的字長為w,那麼它同時就假設了在這種體系結構上對寬度為w的資料的處理最頻繁也是最重要的,它的設計也是從優先提高對w位資料操作的效率來考慮的。 

下面給出三條判斷記憶體對齊的規則,在沒有#pragma pack巨集的情況下,結構體sizeof的大小就是根據以下三條規則得出的:

1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,個資料以後每成員儲存的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如說是陣列,結構體等)的整數倍開始(比如int在32位機為4位元組,則要從4的整數倍位址開始儲存)。

2、結構體作為成員:如果乙個結構裡有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍位址開始儲存 (struct a裡存有struct b,b裡有char,int ,double等元素,那b應該從8的整數倍開始儲存)。

3、收尾工作:結構體的總大小,也就是sizeof的結果, 必須是其內部最大成員的整數倍,不足的要補齊,但是如果內部最大成員的大小大於編譯器預設的對齊大小,那麼結構體的總大小必須是編譯器預設大小的整數倍,即base=min(max(sizeof(s.a), sizeof(s.b),...sizeof(s.n)), default),其中default=#pragma pack(n)

下面看乙個例子:

typedef struct bb

bb;typedef struct aa

aa;int main();

struct s2;

在gcc下, sizeof(struct s2) = 20, 但在vc 6.0下卻是24! 為什麼會是這樣的呢?這就涉及到編譯器的預設對齊和三原則中的原則三的問題了。對於上面結構體s2,如果不考慮記憶體對齊,那麼sizeof(s2)的大小是17bytes,如果要進行對齊,這時候需要滿足規則三,在gcc下,編譯器預設對齊的大小是4bytes,而s2最大元素大小是8bytes,所以在gcc下按照4bytes對齊,最終得到的s2的大小就是20bytes;但是在vc6.0下,編譯器預設對齊是8bytes,因此按照8bytes對齊,因而最終得到的s2的大小是24bytes。但是我們可以修改編譯器預設的對齊大小,可以在結構體前後分別加上下面巨集即可:

#pragma pack(n)

...#pragma pack()

經過測試, 在gcc和vc 6.0中,當分別指定n值為1,2,4時,struct s2的大小相同,分別為15, 16, 20。n=1時, 空間最省,但訪問效率低了。但n=8時,gcc 計算的結果為20, vc 6.0計算的結果為24. 貌似使用#pragma pack(8)對gcc不起作用,還是按預設的4位元組對齊。為什麼對於#pragma pack(8)這種情況,gcc不起作用呢?這個又回到了上面所提到的問題,即在gcc下只支援1,2,4對齊。那是否我們就無能為力了呢?非也,如果非要指定gcc按8位元組對齊也是有辦法的,可以使用__attribute__ ((aligned(8))),具體用法如下所示:

struct s1;

struct s2

__attribute__ ((aligned(8)));

這樣,再計算sizeof(struct s2)時,在gcc下得到的結果也是24了。

參考

C C 記憶體位元組對齊詳解

from 例1 include stdafx.h include using namespace std struct a struct b 換乙個順序 int main 其輸出結果為 24 換行 16 不同樣結構體包含相同的元素型別,為什麼得到的長度不相同呢?這就 牽扯到 資料對齊 1.什麼是資料...

記憶體對齊之主文 C C 位元組對齊詳解

發表於2010 年 09 月 05 日 由linuxsong 一.什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則...

C C 記憶體對齊

一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的...