2012-11-07 34 views
3

可能重複:
Why isn’t sizeof for a struct equal to the sum of sizeof of each member?自定義類的C++ sizeof返回不正確的值?

考慮下面的類,沒有其他數據成員:

typedef uint32_t id_t; 
typedef int64_t loc_t; 

class foo: 
{ 
public: 
    enum bar : uint8_t 
    { 
     BAR1, 
     BAR2, 
     BAR3 
    }; 
private: 
    id_t id; 
    loc_t start; 
    loc_t stop; 
    bar std; 
}; 

任何人都可以解釋爲什麼:

的sizeof(id_t)返回4 ...
的sizeof(loc_t)返回8 ...
的sizeof(巴)返回1 ...

4+(2 * 8)1 = 21

然而:

的sizeof(FOO)返回32?

拆卸杆枚舉類型的uint8_t要求僅成功地製作的sizeof(巴)返回4(INT)而的sizeof(富)仍返回32時24能夠適當字節對齊的。

編輯:爲什麼已經圓滿的回答。我感謝所有評論爲每個人帶來不同細節的人。

我需要的修復是能夠使用sizeof()創建文件位置偏移量。因此,當我以二進制格式將文件寫入文件時,如果稍後給出它的位置,我可以立即找到該文件的位置。如果我找到一個優雅的解決方案,我會在此更新。

+0

這聽起來像你已經意識到如果對齊的概念。對齊計算的哪一部分是你不瞭解的? – Mysticial

+0

我只是沒有想到擴展到8字節對齊......我的想法是24字節(在實際存儲爲「int」的情況下)將被對齊。在bames53下面明確地表明瞭我的判斷錯誤。 – user1445306

回答

1

的類型可能是8字節由於int64_t s對齊,所以

sizeof(id_t) + 4 bytes padding + 2*sizeof(loc_t) + `sizeof(uint8_t)` + padding up to the next multiple of 8 = 
4 + 4 bytes of padding + 16 + 1 + (padding up to the next multiple of 8) = 
25 + padding to multiple of 8 = 
32 

一些編譯器有填充警告(鐺具有-Wpadded):

warning: padding class 'foo' with 4 bytes to align 'start' [-Wpadded] 
    loc_t start; 
     ^
warning: padding size of 'foo' with 7 bytes to alignment boundary [-Wpadded] 
class foo 
    ^

您還可能有能夠使用編譯器擴展進行控制,如#pragma pack(1)

#pragma pack(1) 
class foo: 
{ 
public: 

當然這是一個性能損失,但這種方式sizeof(foo)出現在這個系統上爲我21。

+0

我想我在考慮字節對齊的問題,謝謝你和Sarang對我的理解,我認爲這個填充將不太實際,更傾向於2或4字節對齊。 – user1445306

1

這是因爲內存對齊。 處理器根據總線寬度獲取數據,32位操作系統將在8字節邊界上對齊4字節邊界和64位操作系統上的數據。 非對齊內存需要兩次讀取內存並導致性能下降。

閱讀所有關於此內存對齊:

  1. http://www.devx.com/tips/Tip/13265
  2. http://msdn.microsoft.com/en-us/library/83ythb65.aspx
+0

忍者編輯對不起。我知道它會嘗試某種字節對齊方式。但在枚舉需要一個完整的4字節整數的情況下,總大小應該是24對嗎?而且24會產生適當的字節對齊嗎? – user1445306

+0

@ user1445306,對齊依賴於編譯器和依賴於結構。如果編譯器確定它最適合性能,則總大小可以是24,32或甚至64或其他。 – Griwes

+0

我想我得看看我的交叉編譯工具(基於x86_64 Linux的嵌入式Linux for ARM)的所有值是什麼 – user1445306

1

這是由於填充。編譯器可能會在結構中留下「空格」,以確保結構內的變量完全對齊,以便更有效地訪問。

您可以重寫默認的結構成員對齊方式(至少在MSVC中,通過指定#pragma pack

+0

得到了GCC的答案?我嘗試了__attribute __((packed))和((align)... – user1445306