C語言的內存對齊

引言

 

先看下面這段程序

運行結果(輸出)是:

sizeof(C):12

sizeof(D):8

2個結構體,成員個數,成員類型都一樣,不同的只是成員的順序,最終sizeof的結果卻不相同。要解釋這個問題就需要說明內存對齊。

 

爲什麼要對齊

 

爲了能使CPU對變量進行高效快速的訪問,變量的起始地址應該具有某些特性,即所謂的"對齊"。

 

基本概念

 

數據類型自身的對齊值: 一般地(32位機),對於char型數據,其自身對齊值爲1,對於short型爲2,對於int,float,double類型,其自身對齊值爲4,單位字節。

結構體或者類的自身對齊值: 其成員中自身對齊值最大的那個值。

指定對齊值: #pragma pack (value)時的指定對齊值value。

數據成員、結構體和類的有效對齊值: 自身對齊值和指定對齊值中小的那個值。

因此,32位機中,#pragma pack(16)是沒有意義的(long long的對齊值爲8),原因是有效對齊值取自身對齊和指定對齊中小的那個值。

另外,不同的編譯器有默認的指定對齊值(這也是爲什麼同一個結構在不同編譯器中sizeof結果不同的原因),如VS系列默認對齊方式爲#pragma pack(8),也就是說VS默認以8個字節對齊(如果結構體中某個成員的sizeof大於8)。VC6.0中可以這樣修改默認的指定對齊方式:

[Project]|[Settings],c/c++選項卡Category的Code Generation選項的Struct Member Alignment中修改。

顯然,編碼時,可以通過#pragma動態地修改結構體的指定對齊值。

 

對齊原則

 

對齊方式影響結構體成員在結構體中的偏移,不妨設編譯器指定對齊參數爲n,對於結構體中的某一成員item,它相對於結構首地址的實際字節對齊數目X應該滿足以下規則:

X = min ( n, sizeof(item) )

例如,對於結構體 struct A {char a; int b};

當位於32位系統,n=8時:

a的偏移爲0,

b的偏移爲4,中間填充了3個字節, b的X爲4;

當位於32位系統,n=2時:

a的偏移爲0,

b的偏移爲2,中間填充了1個字節,b的X爲2;

 

再如,對於結構體 struct B{int a;char b;char c;int d};

當位於32位系統,n=8時:

a 的偏移爲0,

b的偏移爲4,

c的偏移爲5,

d的偏移爲8,中間填充了2個字節

當位於32位系統,n=2時:

a 的偏移爲0,

b的偏移爲4,

c的偏移爲5,

d的偏移爲6

 

最後,結構的長度必須爲所用過的所有對齊參數的整數倍,不夠就補空字節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章