記憶體對齊是編譯器為了便於cpu快速訪問而採用的一項技術
我們先從乙個例子開始,對下面的類(或者結構體)
class
node
no;
sizeof(no)的值是多少呢,如果你的回答是7(1+4+2),那麼你應該認真閱讀下面的內容。可以在編譯器上試試,輸出的結果是12,這就是記憶體對齊的結果。
效能原因:資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。
編譯器一般按照幾個位元組對齊呢?本文中兩個編譯器預設按照類中最大型別長度來對齊,我麼也可以使用語句#pragma pack(i)(i =1,2,4,8,16)來設定對齊位元組數目,vs還可以在專案屬性-配置屬性-c/c++-**生成-結構成員對齊設定。
對齊規則如下:
如果設定了記憶體對齊為 i 位元組,類中最大成員對齊位元組數為j,那麼整體對齊位元組n = min(i, j) (某個成員的對齊位元組數定義:如果該成員是c++自帶型別如int、char、double等,那麼其對齊位元組數=該型別在記憶體中所佔的位元組數;如果該成員是自定義型別如某個class或者struct,那個它的對齊位元組數= 該型別內最大的成員對齊位元組數《詳見例項4》)
每個成員對齊規則:類中第乙個資料成員放在offset為0的位置;對於其他的資料成員(假設該資料成員對齊位元組數為k),他們放置的起始位置offset應該是min(k, n) 的整數倍
整體對齊規則:最後整個類的大小應該是n的整數倍
當設定的對齊位元組數大於類中最大成員對齊位元組數時,這個設定實際上不產生任何效果(例項2);當設定對齊位元組數為1時,類的大小就是簡單的把所有成員大小相加
我們通過以下幾個例項來分析
例項1:(沒有指定對齊位元組,則n = 最大成員(int i)的大小4)
class
node
此時成員共占用[0~9]10個位元組,還要整體對齊,大小應該是4的倍數,即12
例項2:(假設指定對齊位元組為8,那麼n = min(8,4) = 4)
class
node
成員共佔據[0~7]8個位元組,剛好是4的倍數,因此大小是8
例項3:(假設指定對齊位元組是2,則n = min(2,4) = 2)
class
node
此時成員共占用[0~7]8個位元組,剛好是4的倍數,因此大小是8
例項4:(按照預設設定)
class
temp
;
由例項1可知,預設對齊情況下,temp的大小是12,temp的對齊位元組數是:三個成員取最大的,即為4;
對於node,n = 其三個成員對齊位元組數取最大,即等於t的對齊位元組數,也就是 4。
class
node
此時成員共占用[0~17]18個位元組,還要整體對齊,大小應該是4的倍數,因此大小是20
例項5:(默然設定)
對於node,n = 其三個成員對齊位元組數取最大,即等於d的對齊位元組數,也就是 8。
class
node
此時成員共占用[0~25]26個位元組,還要整體對齊,大小應該是8的倍數,因此大小是32.
類繼承時的記憶體對齊
考慮如下類
class
aclass
b:public
aclass
c:public
b
sizeof(c)結果是多少呢,gcc和vs給出了不同的結果,分別是8、16
gcc中:c相當於把所有成員i、c1、c2、c3當作是在乙個class內部,(先繼承後對齊)
**
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 ...