#pragma pack(8)
struct s1;
struct s2 ;
#pragma pack()
sizeof(s2)結果為24.
成員對齊有乙個重要的條件,即每個成員分別對齊.即每個成員按自己的方式對齊.
也就是說上面雖然指定了按8位元組對齊,但並不是所有的成員都是以8位元組對齊.其對齊的規則是,每個成員按其型別的對齊引數(通常是這個型別的大小)和指定對齊引數(這裡是8位元組)中較小的乙個對齊.並且結構的長度必須為所用過的所有對齊引數的整數倍,不夠就補空位元組.
s1中,成員a是1位元組預設按1位元組對齊,指定對齊引數為8,這兩個值中取1,a按1位元組對齊;成員b是4個位元組,預設是按4位元組對齊,這時就按4位元組對齊,所以sizeof(s1)應該為8;
s2中,c和s1中的a一樣,按1位元組對齊,而d 是個結構,它是8個位元組,它按什麼對齊呢?對於結構來說,它的預設對齊方式就是它的所有成員使用的對齊引數中最大的乙個,s1的就是4.所以,成員d就是按4位元組對齊.成員e是8個位元組,它是預設按8位元組對齊,和指定的一樣,所以它對到8位元組的邊界上,這時,已經使用了12個位元組了,所以又新增了4個位元組的空,從第16個位元組開始放置成員e.這時,長度為24,已經可以被8(成員e按8位元組對齊)整除.這樣,一共使用了24個位元組.
a bs1的記憶體布局:11**,1111,
c s1.a s1.b d
s2的記憶體布局:1***,11**,1111,****11111111
這裡有三點很重要:
1.每個成員分別按自己的方式對齊,並能最小化長度
2.複雜型別(如結構)的預設對齊方式是它最長的成員的對齊方式,這樣在成員是複雜型別時,可以最小化長度
3.對齊後的長度必須是成員中最大的對齊引數的整數倍,這樣在處理陣列時可以保證每一項都邊界對齊
#pragma pack(4)
class testb ;
int nsize = sizeof(testb);
這裡nsize結果為12,在預料之中。
現在去掉第乙個成員變數為如下**:
#pragma pack(4)
class testc
;int nsize = sizeof(testc);
按照正常的填充方式nsize的結果應該是8,為什麼結果顯示nsize為6呢?
事實上,很多人對#pragma pack的理解是錯誤的。
#pragma pack規定的對齊長度,實際使用的規則是:
結構,聯合,或者類的資料成員,第乙個放在偏移為0的地方,以後每個資料成員的對齊,按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。
也就是說,當#pragma pack的值等於或超過所有資料成員長度的時候,這個值的大小將不產生任何效果。
而結構整體的對齊,則按照結構體中最大的資料成員 和 #pragma pack指定值 之間,較小的那個進行。
具體解釋
#pragma pack(4)
class testb
;這個類實際佔據的記憶體空間是9位元組
類之間的對齊,是按照類內部最大的成員的長度,和#pragma pack規定的值之中較小的乙個對齊的。
所以這個例子中,類之間對齊的長度是min(sizeof(int),4),也就是4。
9按照4位元組圓整的結果是12,所以sizeof(testb)是12。
如果#pragma pack(2)
class testb
;//可以看出,上面的位置完全沒有變化,只是類之間改為按2位元組對齊,9按2圓整的結果是10。
//所以 sizeof(testb)是10。
最後看原貼:
現在去掉第乙個成員變數為如下**:
#pragma pack(4)
class testc
;//整個類的大小是5位元組,按照min(sizeof(short),4)位元組對齊,也就是2位元組對齊,結果是6
//所以sizeof(testc)是6。
感謝michael
提出疑問,在此補充:
當資料定義**現__declspec( align() )時,指定型別的對齊長度還要用自身長度和這裡指定的數值比較,然後取其中較大的。最終類/結構的對齊長度也需要和這個數值比較,然後取其中較大的。
可以這樣理解, __declspec( align() ) 和 #pragma pack是一對兄弟,前者規定了對齊的最小值,後者規定了對齊的最大值,兩者同時出現時,前者擁有更高的優先順序。
__declspec( align() )的乙個特點是,它僅僅規定了資料對齊的位置,而沒有規定資料實際占用的記憶體長度,當指定的資料被放置在確定的位置之後,其後的資料填充仍然是按照#pragma pack規定的方式填充的,這時候類/結構的實際大小和記憶體格局的規則是這樣的:
在__declspec( align() )之前,資料按照#pragma pack規定的方式填充,如前所述。當遇到__declspec( align() )的時候,首先尋找距離當前偏移向後最近的對齊點(滿足對齊長度為max(資料自身長度,指定值) ),然後把被指定的資料型別從這個點開始填充,其後的資料型別從它的後面開始,仍然按照#pragma pack填充,直到遇到下乙個__declspec( align() )。
當所有資料填充完畢,把結構的整體對齊數值和__declspec( align() )規定的值做比較,取其中較大的作為整個結構的對齊長度。
特別的,當__declspec( align() )指定的數值比對應型別長度小的時候,這個指定不起作用。
結構體的空間占用
本文主要包括二個部分,第一部分重點介紹在vc中,怎麼樣採用sizeof來求結構的大小,以及容易出現的問題,並給出解決問題的方法,第二部分總結出vc中sizeof的主要用法。1 sizeof應用在結構上的情況 請看下面的結構 struct mystruct 對結構mystruct採用sizeof會出現...
結構體共用體占用空間大小區別 記憶體對齊計算
題目來自牛客網 在32位機器上 設有以下說明和定義 typedef union date struct data too date max 則語句 printf d sizeof struct data sizeof max 的執行結果是 52共享體 union 維護足夠的空間來置放多個資料成員中的...
WinCE 下結構體占用空間的分析
年前辭職了,準備年後找工作。所以在網上查詢一下 c c 基礎方面的面試題,個人感覺這方面還是要準備一下。雖然後面的應聘沒有用到所準備的這些,算是學習一下。在學習過程中,注意到一些關於結構體占用記憶體空間大小 sizeof 與 padding byte 的問題,覺得挺有趣的。在 wince 以前的小系...