2012-11-07 39 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