結構體內存對齊

2021-07-03 05:31:49 字數 2803 閱讀 2823

關於結構體內存對齊

一、記憶體對齊的原因

大部分的參考資料都是如是說的:

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的最大成員長度。

三、試驗

我們通過一系列例子的詳細說明來證明這個規則吧!

我試驗用的編譯器包括gcc 3.4.2和vc6.0的c編譯器,平台為windows xp + sp2。

我們將用典型的struct對齊來說明。首先我們定義乙個struct:

#pragma pack(n) /* n = 1, 2, 4, 8, 16 */

struct test_t ;

#pragma pack(n)

首先我們首先確認在試驗平台上的各個型別的size,經驗證兩個編譯器的輸出均為:

sizeof(char) = 1

sizeof(short) = 2

sizeof(int) = 4

我們的試驗過程如下:通過#pragma pack(n)改變「對齊係數」,然後察看sizeof(struct test_t)的值。

1、1位元組對齊(#pragma pack(1))

輸出結果:sizeof(struct test_t) = 8 [兩個編譯器輸出一致]

分析過程:

1) 成員資料對齊

#pragma pack(1)

struct test_t ;

#pragma pack()

成員總大小=8

2) 整體對齊

整體對齊係數 = min((max(int,short,char), 1) = 1

整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 8 /* 8%1=0 */ [注1]

2、2位元組對齊(#pragma pack(2))

輸出結果:sizeof(struct test_t) = 10 [兩個編譯器輸出一致]

分析過程:

1) 成員資料對齊

#pragma pack(2)

struct test_t ;

#pragma pack()

成員總大小=9

2) 整體對齊

整體對齊係數 = min((max(int,short,char), 2) = 2

整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 10 /* 10%2=0 */

3、4位元組對齊(#pragma pack(4))

輸出結果:sizeof(struct test_t) = 12 [兩個編譯器輸出一致]

分析過程:

1) 成員資料對齊

#pragma pack(4)

struct test_t ;

#pragma pack()

成員總大小=9

2) 整體對齊

整體對齊係數 = min((max(int,short,char), 4) = 4

整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 12 /* 12%4=0 */

4、8位元組對齊(#pragma pack(8))

輸出結果:sizeof(struct test_t) = 12 [兩個編譯器輸出一致]

分析過程:

1) 成員資料對齊

#pragma pack(8)

struct test_t ;

#pragma pack()

成員總大小=9

2) 整體對齊

整體對齊係數 = min((max(int,short,char), 8) = 4

整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 12 /* 12%4=0 */

5、16位元組對齊(#pragma pack(16))

輸出結果:sizeof(struct test_t) = 12 [兩個編譯器輸出一致]

分析過程:

1) 成員資料對齊

#pragma pack(16)

struct test_t ;

#pragma pack()

成員總大小=9

2) 整體對齊

整體對齊係數 = min((max(int,short,char), 16) = 4

整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 12 /* 12%4=0 */

結構體內存對齊

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

結構體內存對齊

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

結構體內存對齊

對齊規則 每個特定平台上的編譯器都有自己的預設 對齊係數 也叫對齊模數 程式設計師可以通過預編譯命令 pragma pack n n 1,2,4,8,16來改變這一係數,其中的n就是你要指定的 對齊係數 規則 1 資料成員對齊規則 結構 struct 的資料成員,第乙個資料成員放在offset為0的...