结构对齐--__packed与#pragma pack
1、ANSI C規定
????? ANSI C規定一種結構類型的大小是它所有字段的大小以及字段之間或字段尾部的填充區大小之和。
????? 填充區就是為了使結構體字段滿足內存對齊要求而額外分配給結構體的空間。
?
????? 那么結構體本身有對齊要求,ANSI C標準規定結構體類型的對齊要求不能比它所有字段中要求最嚴格的那個寬松,可以更嚴格。
?
2、WIN32和Linux平臺下的對齊基本規則
?
????? 許多實際的計算機系統對基本類型數據在內存中存放的位置有限制,它們會要求這些數據的首地址的值是某個數k
(通常它為4或8)的倍數,這就是所謂的內存對齊,而這個k則被稱為該數據類型的對齊模數(alignment modulus)。
????Win32平臺下的微軟C編譯器(cl.exe for 80x86)在默認情況下采用如下的對齊規則:
????任何基本數據類型T的對齊模數就是T的大小,即sizeof(T)。比如對于double類型(8字節),就要求該類型數據的地址總是8的倍數,
而char類型數據(1字節)則可以從任何一個地址開始。
????Linux下的GCC奉行的是另外一套規則(在資料中查得,并未驗證,如錯誤請指正):
????任何2字節大小(包括單字節嗎?)的數據類型(比如short)的對齊模數是2,而其它所有超過2字節的數據類型(比如long,double)
都以4為對齊模數。
?
3、vc6中對齊處理
????vc6中的編譯選項有 /Zp[1|2|4|8|16] ,/Zp1表示以1字節邊界對齊,相應的,/Zpn表示以n字節邊界對齊。
n字節邊界對齊的意思是說,一個成員的地址必須安排在成員的尺寸的整數倍地址上或者是n的整數倍地址上,取它們中的最小值。
也就是:
????min ( sizeof ( member ),??n)
????實際上,1字節邊界對齊也就表示了結構成員之間沒有空洞。?
????
????要使用這個選項,可以在vc6中打開工程屬性頁,c/c++頁,選擇Code Generation分類,在Struct member alignment可以選擇。
?
??? /Zpn選項是應用于整個工程的,影響所有的參與編譯的結構。該缺省/Zp 緊湊值為/Zp8,也就是說,缺省是8字節對齊。
????要專門針對某些結構定義使用對齊選項,可以使用#pragma pack編譯指令。
?
#pragma pack(push) //保存對齊狀態
#pragma pack(1)?? // 1 bytes對齊
typedef struct?
{
??? double dValue1;
??? char?? u8Value2;
??? int??? u32Value3;
} ASampleStructor;
#pragma pack(pop)//恢復對齊狀態
?
??? 上例中,size值為13,說明1字節對齊后,該結構總長為13字節。去掉對齊后,為16字節。
4、ARM平臺中的對齊
?
??? 在ARM平臺的編譯器中,沒有提供象“#pragma pack”這么豐富的帶參數對齊指令,只有一個關鍵字“__packed”。
__packed?限定符將所有有效類型的對齊邊界設置為 1,如果一個結構沒有這個限定符,默認向表數能力最強的那個數據類型對齊。
?
typedef __packed struct?
{
??? double dValue1;
??? char?? u8Value2;
??? int??? u32Value3;
} ASampleStructor;
?
上例中,size值為13,說明1字節對齊后,該結構總長為13字節。去掉__packed對齊后,為16字節。
?
5、一種與對齊相關的可隨時運行在VC環境或ARM(Keil)環境下的定義
?
?????? 我們時常會把嵌入式平臺上的代碼拿到PC環境中去測試,這時環境的差異將使代碼移植變得困難。
下面這種結構,將會使移植變得非常輕松。
?
#ifdef WIN32
#define __packed? //在VC環境下,將此關鍵字定義為空
?
#pragma pack(push) //保存對齊狀態
#pragma pack(1)?? // 1 bytes對齊
#endif
?
typedef __packed struct?
{
??? double dValue1;
??? char?? u8Value2;
??? int??? u32Value3;
} ASampleStructor;
?
#ifdef WIN32
#pragma pack(pop)//恢復對齊狀態
#endif
?
???? 這樣,無論是ARM還是VC,都可以編譯,代碼的同步將非常簡單。
?
???? 不過呢,還有一種方法更為簡單,可以使代碼運行在ARM(Keil)或VC環境下。
#pragma pack(push,1)
typedef? struct?
{
??? double dValue1;
??? char?? u8Value2;
??? int??? u32Value3;
} ASampleStructor;
#pragma pack(pop)
以上內容轉自:http://blog.csdn.net/mcu_hong/article/details/8702912
總結
以上是生活随笔為你收集整理的结构对齐--__packed与#pragma pack的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Error - section 'Int
- 下一篇: C99的各类头文件