c語言中記憶體對齊問題

2022-07-16 05:48:11 字數 2499 閱讀 7235

一、記憶體對齊的原因 大部分的參考資料都是如是說的: 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值的大小將不產生任何效果。

三、試驗 我們通過一系列例子的詳細說明來證明這個規則吧! 我試驗用的編譯器包括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 */

四、結論 8位元組和16位元組對齊試驗證明了「規則」的第3點:「當#pragma  pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果」。另外記憶體對齊是個很複雜的東西,上面所說的在有些時候也可能不正確。呵呵^_^

[注1] 什麼是「圓整」? 舉例說明:如上面的8位元組對齊中的「整體對齊」,整體大小=9 按 4 圓整 =  12 圓整的過程:從9開始每次加一,看是否能被4整除,這裡9,10,11均不能被4整除,到12時可以,則圓整結束。

C語言中記憶體對齊問題

在日常的開發工作中,時常要用到結構體的定義工作,但是結構體中資料的定義順序是否合理直接影響了結構體所佔記憶體的大小,所以了解c語言中記憶體對齊的知識十分有必要。關於記憶體對齊的原則,我們首先討論沒有定義巨集 pragam pack 的情況,在該巨集沒有定義的情況之下,c語言中結構體的記憶體對齊問題主...

C語言中記憶體對齊詳解

首先由乙個程式引入話題 1 環境 vc6 windows sp22 程式13 include iostream 45 using namespace std 67 struct st1 8 1314 struct st215 20 21int main 2227 程式的輸出結果為 sizeof st...

C語言中的記憶體對齊

這階段一直想寫一篇部落格,其實有好多東西,先寫一下c語言中的記憶體對齊吧。大家都知道,在c語言中定義乙個變數,char是占用乙個位元組的,int占用四個位元組,float占用四個位元組,double占用八個位元組,short占用兩個位元組,long int占用四個位元組,long long神馬的是6...