結構體的記憶體對齊問題

2021-06-20 13:34:03 字數 1552 閱讀 6030

在c、c++筆試中,記憶體對齊問題經常考,儘管這樣,這幾年來我一直忽略了這個問題,記憶中一直是大學課本中struct與union的區別,那時候也不曾有提及過記憶體對齊,現在想起來,真是非常大的漏洞。而且很多筆試想當然的覺得struct的大小就是內部所有變數大小的和,卻不知這種錯誤的答案讓多少面試官默默的鄙視,直到前一次面試,面試官諷刺到:「作為乙個c++程式設計師,竟然不知道記憶體對齊這樣的基礎知識。。。」,深感愧疚,我對不起這些年與c++的朝夕相處啊!回來後查了一些文章,又做了幾個測試,才搞明白其中的原理,現記錄一下,方便有同樣經歷的猿類自查。

現舉個例子:

typedef structnode;

cout<

以前, 我一直以為輸出的結果是5(1 + 4)  直到。。。今天它怎麼變成了8!!!

分析一下,經過網上查詢資料,兩個原因:

1、平台原因(移植原因):不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。

2、效能原因:資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。

原則:每個特定平台上的編譯器都有自己的預設「對齊係數」(也叫對齊模數)。程式設計師可以通過預編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一係數,其中的n就是你要指定的「對齊係數」。

對齊步驟:

1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的對齊按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。

2、結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。

3、結合1、2顆推斷:當#pragma pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果。

備註:陣列成員按長度按陣列型別長度計算,如char t[9],在第1步中資料自身長度按1算,累加結構體時長度為9;第2步中,找最大資料長度時,如果結構體t有複雜型別成員a的,該a成員的長度為該複雜型別成員a的最大成員長度。

廢話說了這麼多,我覺得還是使用言簡意賅的畫圖詮釋一下。

結構體 node

anull

null

nullbb

bb

意思是char佔了4個位元組,第乙個位元組記憶體值,後面三個沒有用到,int使用了四個位元組

再看乙個例子

typedef struct{

char a;

short b;

int c;

char d;

}node;

cout<

輸出的結果應該是12,不是8,用**的形式表示一下,如下:ab

bnullcc

ccdnull

null

null

我覺得規律是,結構體的大小一定是內部最大型別大小的整數倍,因為邊界以最大型別大小確定的。

以後不會再在這裡翻船了!銘記!

結構體對齊(記憶體對齊

有的時候,在腦海中停頓了很久的 顯而易見 的東西,其實根本上就是錯誤的。就拿下面的問題來看 structt 使用sizeof t 將得到什麼樣的答案呢?要是以前,想都不用想,在32位機中,int是4個位元組,char是1個位元組,所以t一共是5個位元組。實踐出真知,在vc6中測試了下,答案確實8個位...

記憶體對齊 結構體對齊

現在已知32位機器上各種資料型別的長度如下 char 1 有符號無符號同 short 2 有符號無符號同 int 4 有符號無符號同 long 4 有符號無符號同 float 4 double 8 重要規則 1,複雜型別中各個成員按照它們被宣告的順序在記憶體中順序儲存,第乙個成員的位址和整個型別的位...

結構體中記憶體對齊問題

首先,在記憶體分配上,如果是單獨的乙個資料型別,對齊方式如下 常用型別的對齊方式 型別 對齊方式 變數存放的起始位址相對於結構的起始位址的偏移量 char 偏移量必須為sizeof char 即1的倍數 int 偏移量必須為sizeof int 即4的倍數 double 偏移量必須為sizeof d...