2010-07-16 28 views
1

被包裝在C/C的結構的成員++? (由填充我的意思是他們是緊湊和領域中還沒有一個內存空間)場對準/ C++

+7

'編譯器錯誤:「對齊」和「的members'.' – kennytm 2010-07-16 16:06:48

回答

9

那不是對準手段,沒有,沒有特別的定位或包裝有保證。元素將按順序排列,但編譯器可以在其選擇的位置插入填充。這實際上創建(有用的)對齊。例如,對於x86:

struct s 
{ 
    char c; 
    int i; 
}; 

在c和i之間可能(但不一定)是三個字節。這使得i將一個單詞邊界,它可以提供更快的內存訪問(在某些架構,必須)對齊。

從C99§6.7.2.1:

Each non-bit-field member of a structure or union object is aligned in an implementation- defined manner appropriate to its type.

+1

這需要照顧,以及如果你正在寫的結構與期待名詞轉換爲二進制文件並以4字節塊回讀。您必須保持4字節的邊界,否則您將丟失結構到二進制文件的關係,因爲數據將不會正確對齊。 – 2010-07-16 16:12:53

+1

我正在編寫一些代碼來讀取文件中的二進制數據(特定格式,在其他地方定義),並且碰到了@ 0A0D描述的問題。我使用'#pragma pack(1)'固定了它 - 也使用'#pragma pack(push)'(之前)和'#pragma pack(pop)'(在結構之後)按照[本部分](http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86)。 – lindes 2011-02-23 06:14:32

2

一般不會。一些信息here

根據不同的編譯器,你可以引入編譯指示來幫助(從上面的鏈接):

#pragma pack(push) /* push current alignment to stack */ 
#pragma pack(1)  /* set alignment to 1 byte boundary */ 

struct MyPackedData 
{ 
    char Data1; 
    long Data2; 
    char Data3; 
}; 

#pragma pack(pop) /* restore original alignment from stack */ 
+0

謝謝!我也發現了這一點,但我想確保它也存在於SO上。 :) – lindes 2011-02-23 06:16:24

2

通常(但沒有擔保),一個struct的成員word -aligned。這意味着小於一個單詞大小的字段將被填充以佔據整個單詞。

然而,當結構的下一個成員適合在同一個單詞內時,編譯器會將兩個成員放到同一個單詞中。這是更有效的空間明智的,但根據您的平臺,檢索所述成員可能會更加昂貴的計算。

在Cygwin下使用GCC該程序我的32位系統,...

#include <iostream> 

struct foo 
{ 
    char a; 
    int b; 
    char c; 
}; 

int main(int argc, char** argv) 
{ 
    std::cout << sizeof(foo) << std::endl; 
} 

輸出「12」,因爲這兩個字符都是字對齊的並且佔用每4個字節。

然而,切換結構來

struct foo 
{ 
    char a; 
    char c; 
    int b; 
}; 

並且輸出是「8」,因爲這兩個字符彼此相鄰可以裝在單個字。

+0

這不是字對齊。如果是的話,你的第二個例子中的'a'和'c'將佔用單獨的單詞。 ;) – jalf 2010-07-18 10:28:44

+0

@jalf:好的,我在頂部擴展了我的解釋。我討厭什麼時候會發生......我說的和我的意思是有衝突的:X – 2010-07-18 11:38:46

4

你要求的是包裝,對齊是不同的。兩者都不在該語言的範圍內,並且針對每個實現都是特定的。看看here

0

可以打包字節以節省內存。例如,pack(2)會告訴成員比一個字節更長的時間打包成兩個字節,以便維護一個雙字節邊界,以便任何填充成員都是兩個字節長。有時包裝被用作標準通信協議的一部分,它在預期具有一定的尺寸。下面是維基百科不得不說的C/C++和padding:

Padding is only inserted when a structure member is followed by a member with a larger alignment requirement or at the end of the structure. By changing the ordering of members in a structure, it is possible to change the amount of padding required to maintain alignment. For example, if members are sorted by ascending or descending alignment requirements a minimal amount of padding is required. The minimal amount of padding required is always less than the largest alignment in the structure. Computing the maximum amount of padding required is more complicated, but is always less than the sum of the alignment requirements for all members minus twice the sum of the alignment requirements for the least aligned half of the structure members.

Although C and C++ do not allow the compiler to reorder structure members to save space, other languages might.

由於結構的,編譯器將事情的話,有時必須格外小心,如果你是依靠結構的大小是一個一定的大小。例如,對齊char和int。

0

默認情況下,它們未被打包,而是根據機器的設置方式進行字對齊。如果你確實希望他們被打包。然後你就可以在你的結構聲明中這樣結尾使用__attribute__((__packed__))

struct abc { 
    char a; 
    int b; 
    char c; 
}__attribute__((__packed__)); 

然後,

struct abc _abc; 

_abc將被包裝。

參考:http://www.grok2.com/structure_packing.html

0

看到了同樣結構的變化,一些輸出可以給出一個關於正在發生的事情的線索。在閱讀this後,如果我沒有弄錯,小字體會填充爲字長。

struct Foo { 
    char x ; // 1 byte 
    int y ; // 4 byte 
    char z ; // 1 byte 
    int w ; // 4 byte 
}; 
struct FooOrdered { 
    char x ; // 1 byte 
    char z ; // 1 byte 
    int y ; // 4 byte 
    int w ; // 4 byte 
}; 


struct Bar { 
    char x ; // 1 byte 
    int w ; // 4 byte 
}; 
struct BarSingleType { 
    char x ; // 1 byte 
}; 

int main(int argc, char const *argv[]) { 
    cout << sizeof(Foo) << endl; 
    cout << sizeof(FooOrdered) << endl; 
    cout << sizeof(Bar) << endl; 
    cout << sizeof(BarSingleType) << endl; 
    return 0; 
} 

在我的環境輸出是這樣的:

16 
12 
8 
1