C++结构体大小:2+4+2+2+4 = 16

3

3
为什么结构体的sizeof不等于每个成员的sizeof之和? - Michael Burr
1
http://en.wikipedia.org/wiki/Sizeof#Structure_padding - anon
1
谁说short是2,int是4的? - Martin York
1
@Martin York 他说他正在使用g++,如果他使用的是x86,则它们将为2和4个字节。这是非常有可能的... - Ramónster
一旦问题得到解答,如果你没有任何要补充的内容,我不明白为什么还要再添加一个“我也是”的回答。拜托了。 - marcc
9个回答

12

这是因为4字节的int类型需要对齐到4字节边界,所以在bfType后面会有2字节的填充。


8

对齐。 在您的平台上,整数需要4字节对齐,而短整型需要2字节对齐。

+0 -1 : bfType
+2 -3 : <padding>
+4 -7: bfSize
+8 -9: bfReserve1
+10 -11: bfReserve2
+12 -15: bfOffBits
-------------
16 bytes

对齐是很重要的,因为未对齐的结构在许多架构中需要额外的工作。


7

结构体中的各个字段需要适当对齐。编译器会在结构体中填充额外的空间,以满足对齐要求。

如果您不想这样做,可以使用UNALIGNED宏。


6
我认为“unaligned”不是一个关键字。这可能是编译器特定的术语。 - GManNickG
1
答案很好,但是“unaligned”不是C++关键字。 - coppro
2
在GCC中,您可以使用__attribute__((packed));来指示您希望取消对齐字段。例如:unsigned short bfType attribute((packed)); - Joey Adams
2
__unaligned是Visual C++的扩展,并不被例如g++支持(问题明确标识为所使用的实现)。任何这样的宏都将固有地与实现相关。 - Pavel Minaev
每个成员的对齐方式都有一个最小要求(由硬件设置)。但编译器可以出于其他原因(例如优化)添加更多填充。 - Martin York
显示剩余3条评论

5
我认为你的编译器对字段使用了4字节对齐。

2
这个问题是由一个叫做“对齐”的概念引起的。在许多情况下,希望将数字放置在地址上,这个地址是数字字节大小的倍数(最大值通常为平台的指针大小)。被放置在这样的位置的变量被称为“对齐到n字节边界”,其中n是数字。这个的确切影响取决于处理器。如果数据被正确地对齐,许多处理器执行数学运算速度更快。有些处理器甚至无法对不适当对齐的数据执行操作(有时甚至是加载操作)-为了处理这样的数据,必须将其加载到两个寄存器中,然后执行一系列位移和掩码操作以获取可用值,然后再将其放回。可以将其视为将int的一半存储在两个桶中,并需要将它们组合在一起以使用它,而不是简单地将整个int存储在一个桶中。
在您的情况下,初始的bfType可能需要对齐到2字节边界,而bfSize可能需要对齐到4字节边界。编译器必须通过将整个结构对齐到4字节并在bfType和bfSize之间留下2个未使用的字节来适应此情况。
但是,在同一系统上编译时,填充可能是一致的,可能取决于编译器选项和使用的特定ABI(通常情况下,除非您试图使事物不兼容,否则在同一平台上是安全的)。可以自由地创建具有相同前5个成员的另一个结构,并且它们将占用另一个结构的16个字节,位置完全相同。
如果真的需要避免这种行为,则必须检查编译器文档。大多数编译器都提供了一个属性或关键字来声明变量没有对齐,以及另一个关键字来指示结构体不应该有填充。但是这些在一般情况下很少使用。

1
你可以使用#pragma pack指令来避免结构体填充。

1

ISO C++03,9.2[class.mem]/12:

非联合类的非静态数据成员在声明时没有中间访问说明符的情况下分配,以便稍后的成员在类对象内具有更高的地址。通过访问说明符分隔的非静态数据成员的分配顺序是未指定的(11.1)。实现对齐要求可能导致两个相邻的成员不会立即相互分配;因此,管理虚函数(10.3)和虚基类(10.1)所需的空间的要求也可能如此。


0
由于内存分配的方式,short类型后面会有填充。

1
确实,那是一个好建议。然而,这里涉及到处理 .bmp 文件的应用程序,所以那不是一个选项。无论如何 +1 ;-) - Joey Adams

0
这是由于对齐导致的 - 编译器必须进行一些填充。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接