C 記憶體對齊

2021-08-29 20:38:05 字數 2873 閱讀 6781

記憶體對齊簡單的例子

#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 ...