2013-02-04 120 views
1

我在我的項目和特定結構的上下文中使用數據結構,我對結構填充有疑問。首先看下面給出的結構。我使用Visual Studio 2008編譯器。關於在C++中的結構填充

typedef struct tagDATA_PACK 
{ 
    DWORD dDataLength; 
    BYTE bFlags; 
    BYTE bAttrib; 
    BYTE bOffset; 
}DATA_PACK; 

問題1:上述結構的大小是多少? 它顯示8個字節。它是正確的。但是,

考慮下面給出的修改結構?

typedef struct tagDATA_PACK 
{ 
    DWORD dDataLength; 
    BYTE bFlags; 
}DATA_PACK; 

這裏大小與上面的8字節結構相同。 我的疑問是,編譯器會在哪裏添加額外的3字節? 是BYTE bFlags還是之前?

所有的答案是非常感謝。

回答

4

標準並未指定結構和類的對齊和填充。完全取決於編譯器。但是,所有理智的編譯器都遵循底層平臺ABI。在你的情況下,平臺是Windows,並且Windows平臺ABI被遵守。

在這種情況下,對於這兩個結構體的填充位於最後一個成員之後。第一個結構有一個額外的填充字節,第二個結構有三個額外的填充字節。

在struct最大類型具有尺寸4.這意味着,整體尺寸將是4。對於這兩種結構的倍數,容納結構體4的最小倍數爲8

每個數據類型具有對齊屬性。一個4字節的數據類型有4的對齊方式。一個2字節的數據類型有一個2的對齊方式。當一個對齊方式爲4的類型被放置在從結構開始的4字節偏移處時被對齊。如果將對齊方式爲2的類型放置在距結構起始位置2個字節的偏移處,則會進行對齊。等等。

成員被放置在尊重成員聲明順序和成員對齊屬性的最小偏移處。

對於填充內部的結構的例子考慮這個結構

struct MyStruct 
{ 
    char c; 
    int i; 
}; 

c的對準是1,和的i對準爲4。所以,c被放置在1個字節邊界上,並i必須放置在4字節邊界上。這意味着c將有偏移量0,那麼會有3個填充字節,然後i將佈置在偏移量爲4.

+0

這意味着編譯器推斷,其中增加了額外的填充字節的地方,不是嗎? – RyanAdamVeet

+0

是的,編譯器決定如何佈局結構。 –

+0

實際上,標準中存在一系列限制,基本上只剩下一種明智的做法。 –

1

編譯器想要什麼時候。如果重要,無論如何你都在做一些不可移植的東西,那麼爲什麼它很重要?

+0

實際上,我爲這個結構和一些保持結構的數據創建了一個BYTE數組。所以,總大小不會是結構本身,而是包括額外的數據緩衝區。變量BYTE bOffset存儲數據偏移地址。我記得當我訪問除結構成員以外的數據時會有什麼問題 – RyanAdamVeet

0

看看這個:

typedef struct myTagDATA_PACK3 
{ 
    char c; 
    double d; 
    int i; 
}DATA_PACK3; 

它顯示了24個字節。即: double:8個字節。 int:4個字節+(4個字節填充)= 8個字節。 char:1個字節+(7個字節填充)= 8個字節。


總計:24個字節。

+0

這個問題到底如何回答? –

+0

嘿,它不,但它仍然很酷! – thang

+0

@DavidHeffernan,這實際上是你的答案的例證。 –

1

儘管所有的答案都是由編譯器決定的,但由於直到編譯器,所以語言規範對佈局有一些限制。這些限制適用於C中的所有結構,C++ 03中的「普通舊數據」(基本上意味着僅使用C中的特性)和C++ 11中的「標準佈局」結構(允許具有構造函數和析構函數)。這些限制是:

  • (Reinterpret-)將結構指針轉換爲第一個成員的類型會生成第一個成員(C++ 11§9.2/ 20)的有效指針。這意味着在第一個成員之前不能填充。
  • 如果聯合中的兩個結構具有相同的初始部分(相同順序中的同一類型的成員),並且通過其中一個聯合初始化聯合,則可以通過其他聯合來訪問這些初始成員(C++ 11§ 9.2/19)。這意味着成員偏移量可能僅取決於之前聲明的成員。

對標準佈局的限制很重要。對於具有基類或虛擬成員的類都不適用。

現在,當不想浪費內存的時候,這實際上只剩下一種實用算法,因此所有編譯器都使用這種算法。這並不意味着所有的編譯器都會爲相同的輸入生成相同的佈局,因爲不同平臺之間各種基本類型的大小和對齊要求不同。該算法是:

  • 鋪陳所述第一構件在偏移0
  • 鋪陳每個下列構件在第一個可用的由它的所需的對準偏移整除。
  • 將結構的大小舍入到任何成員的最大對齊的下一個倍數。
  • 該結構的對齊要求是任何成員的最大對齊。

(我幾乎可以肯定MSDN的MSVC++描述了這個地方,但不能很快找到它)

+0

+1好挖:第 – thang