記憶體對齊簡單的例子
#include
using namespace std;
class a
;int
main()
在classa中總共花費5個位元組。但是輸出的結果是
為什麼大小會是8?這個就需要歸功於c++的記憶體對齊了,我們看下類a中記憶體布局
在a變數後面插入了3個位元組,然後才是b變數。
這個原因是在位元組對齊的作用下,其中規律是:類每個成員相對類首位址的偏移量(offset)都是有效對齊值的整數倍,如有需要編譯器會在成員之間加上填充位元組(alignment)。
我們看下什麼叫做有效對齊位 ,一般情況(先說一般情況)下這個值就是基本資料型別所佔記憶體的大小,一般就是char為1、short為2、int為4、long long為8,也就是說在類中,char變數的有效對齊位是1,那麼它的相對偏移只要是1的倍數也就是任意值,short的相對偏移必須是2的倍數,int相對偏移必須是4的倍數。
上述情況a的偏移量為0是1的倍數,b的有效對齊位大小為4,所以起始位置需要是4才能滿足。
在程式中有效對齊位 = min(預設對齊位,位元組寬度)
預設對齊位在程式通過#prapam pack(n)設定。
我們在上述的**中插入預設對齊位的定義2
#include
using namespace std;
#pragma pack(2)
//預設對齊位
class a
;int
main()
輸出的內容為
這個時候類a中的記憶體布局為
因為b的記憶體對齊位為2,所以它的偏移只需要為2的倍數2,在a變數後面插入了1個位元組。
在類中大小也需要記憶體對齊。
我們在上述的例子中a加入乙個元素
#include
using namespace std;
class a
;int
main()
在這個類中最大額記憶體對齊值是int b為4,當4(a) + 4(b)+c(1)= 9最少還差3個位元組為12,所以需要在末尾填充3個位元組大小就可以滿足這個條件。
在c++類中不單單有成員的變數,如果類含有虛函式,那麼在類中會有乙個虛函式表指標。在使用虛繼承的時候每個虛繼承類都會有乙個虛繼承指標類(如果不清楚的這些的可以了解c++的記憶體布局)
當然虛函式表指標(vfptr)和虛基類表指標(vbtpr)也遵循這個規律。
我們看下以下**的記憶體布局
#include
using namespace std;
class a
;long
long lo;};
class b : virtual public a
;int
main()
編譯後記憶體布局是
base a 中vfptr指標本來只佔4個位元組(在32位機器下),因為lo有效記憶體對齊值為8個記憶體,起始位址需要是8的倍數,所以vfptr後面填充了4個位元組補充。在vbptr後面也是相同,因為birtual base a記憶體對齊值為8所以所以vbptr指標,起始位址為8的倍數。
記憶體對齊不僅僅是體現在類成員的偏移和大小中,同樣也出現在棧,堆中,在棧和堆中都會符合起始位址和記憶體對齊值的倍數。
在堆中連續申請兩塊記憶體不一定是連續的位址,我們採用下面的**驗證是否符合。
#include
using namespace std;
//類a的記憶體對齊值是8
class a
;int
main()
else
} cout <<
"zcount = "
<< zcount << endl;
cout <<
"nzcount = "
<< nzcount << endl;
return1;
}
在堆上申請1百萬個元素,計算位址是否能被8整除。最後輸出結果為
可以看出記憶體對齊在堆上也是相同的
在棧中也是符合的,因為棧中記憶體是連續的,我們可以簡單的把輸出位址檢視是否有記憶體填充的情況。
#include
using namespace std;
//類a的記憶體對齊值是8
class a
;int
main()
我們可以看這段**輸出結果是
前面char記憶體都是連續遞減(棧記憶體增長是由高到底),到a的時候,相差17個位元組。我們用下面圖表示。其實c2和a只相差1個位元組,c2和a的起始位址相差17個位元組。就是因為這1個位元組的填充,a的起始位址才能是記憶體對齊值8整除。
我們可以在不同的編譯器中強制設定記憶體對齊。
參考文獻
gcc中
vc中記憶體對齊相關部落格:
C 記憶體對齊
vc6.0編譯器對記憶體對齊的管理方式遵循以下兩個原則 1.對於結構體內部變數的對齊方式 變數存放的起始位址相對於結構的起始位址的偏移量 char 偏移量必須為sizeof char 即1的倍數 int 偏移量必須為sizeof int 即4的倍數 float 偏移量必須為sizeof float ...
c 記憶體對齊
一.計算struct的size有兩個原則 pragma pack n n是編譯器的對齊位元組數 1 struct中各成員按照對齊原則 在為當前變數 設為a 分配記憶體時,要參考之前所有變數的偏移量之和 設為d d必須是min n,sizeof a 的倍數,否則編譯器會自動在最後補上缺少的位元組數。2...
C 記憶體對齊
c 中的記憶體對齊 記憶體對齊 在我們的程式中,資料結構還有變數等等都需要占有記憶體,在很多系統中,它都要求記憶體分配的時候要對齊,這樣做的好處就是可以提高訪問記憶體的速度。我們還是先來看一段簡單的程式 程式一 1 include 2 using namespace std 3 4structx1 ...