Struct對齊方式

2021-07-03 21:16:35 字數 2155 閱讀 1718

畢業前找工作的經歷讓我發現,很多公司的筆試、面試題中都涉及到了struct的對齊的問題!今天我們就深入探索其中的奧秘!

預設情況下,編譯器為結構體的每個 成員按其自然對界(

natural alignment

)條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第乙個成員的位址和整個結構的位址相同。

即預設對齊方式,是指按結構體的成員中

size

最大的成員對齊。

一般地,可以通過下面的方法來改變預設的對界條件:

使用偽指令#pragma pack (n),編譯器將按照n個位元組對齊;

使用偽指令#pragma pack (),取消自定義位元組對齊方式。

注意:如果#pragma pack (n)中指定的n大於結構體中最大成員的size,則其不起作用,結構體仍然按照size最大的成員進行對界。

首先,讓我們分析下面的**:

分析例子b;

struct b

;

假 設b從位址空間0x0000開始排放。該例子中沒有定義指定對齊值,在筆者環境下,該值預設為4。第乙個成員變數b的自身對齊值是1,比指定或者預設指定 對齊值4小,所以其有效對齊值為1,所以其存放位址0x0000符合0x0000%1=0.第二個成員變數a,其自身對齊值為4,所以有效對齊值也為4, 所以只能存放在起始位址為0x0004到0x0007這四個連續的位元組空間中,複核0x0004%4=0,且緊靠第乙個變數。第三個變數c,自身對齊值為 2,所以有效對齊值也是2,可以存放在0x0008到0x0009這兩個位元組空間中,符合0x0008%2=0。所以從0x0000到0x0009存放的 都是b內容。再看資料結構b的自身對齊值為其變數中最大對齊值(這裡是b)所以就是4,所以結構體的有效對齊值也是4。根據結構體圓整的要求, 0x0009到0x0000=10位元組,(10+2)%4=0。所以0x0000a到0x000b也為結構體b所占用。故b從0x0000到0x000b 共有12個位元組,sizeof(struct b)=12;

------------------------------------

到底為啥編譯器要對struct做對齊處理呢?其實這句話有點片面,編譯器會對所有的**進行對齊處理,不值struct,那到底為啥要這麼做呢?那我們就引用下前人的研究成果來做下說明:

現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。

對齊的作用和原因:各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。比如有些架構的cpu在訪問乙個沒有進行對齊的變數的時候會發生錯誤,那麼在這種架構下程式設計必須保證位元組對齊.其他平台可能沒有這種情況,但是最常見的是如果不按照適合其平台要求對資料存放進行對齊,會在訪問效率上帶來損失。比如有些平台每次讀都是從偶位址開始,如果乙個int型(假設為32位系統)如果存放在偶位址開始的地方,那麼乙個讀週期就可以讀出這32bit,而如果存放在奇位址開始的地方,就需要2個讀週期,並對兩次讀出的結果的高低位元組進行拼湊才能得到該32bit資料。顯然在讀取效率上下降很多。

注釋:**於:

經過上面的介紹,你是否已經對位元組對齊,以及為啥做位元組對齊有了深刻的認識了!可能桀驁不馴的你會提出,我不管這麼多,就是不想做位元組對齊!那也有辦法,因為所有內建變數都是以位元組為單位的,那你就可以通過預編譯命令#pragma pack(push,1) 和 #pragma pack(pop)來將對齊單位設定成1位元組!我們看看下面示例:

#pragma pack( 1)

struct at

;#pragma pack()

int main(void)

執行結果:

7請按任意鍵繼續. . .

怎麼樣?是否達到了目的?at中a的1個位元組+b的1個位元組+c的4個位元組+d的1個位元組 = 7 位元組。但是在用#pragma pack的時候一定要注意,在你定義的標頭檔案中#pragma pack(push,1) 和 #pragma pack(pop)必須成對出現,並且只用於設定你的**部分,不然其他人的**包了你的庫的標頭檔案就會發生錯誤,比如別人是按預設位元組對齊編譯的庫,結果你是按1位元組進行的設定,包了你的標頭檔案時,位元組對齊就變成了1位元組,但二進位制庫里還是原來預設位元組對齊,就會導致在程式執行時取值錯誤!而且這種錯誤有時很難發現!

struct對齊方式

結構體的記憶體分配原則 原則1 資料成員對齊規則 結構 struct或聯合union 的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小的整數倍開始 比如int在32位機為4位元組,則要從4的整數倍位址開始儲存 原則2 結構體作為成員 如果乙個結構裡有...

struct 成員的對齊方式

用乙個巨集定義find求結構體struct s中某個成員變數member相對struct s的偏移量.思考 若struct s的位址為0,則其成員member的位址就是其相對於s的偏移量 擴充套件 1 sizeof struct s 不一定等於 sizeof struct s中的每乙個成員 的和 2...

struct 結構體內存對齊方式

以下都以32位機器為例分析結構體型別的變數在記憶體裡的儲存 一 1.結構體變數的儲存位置都是在記憶體中尋找位址是該變數自身大小整數倍開始儲存的。2.結構體型別變數的總大小應是該型別成員中最大資料型別的整數倍。就此兩點,可以解決所有問題,對於第一條,應該注意每一位成員存放的首位址定為自身的整數倍。例子...