在结构中包装类型会导致额外的填充
Can wrapping a type in a struct cause additional padding?
可能重复:
具有单个元素的结构的大小
给定任何类型的A
和以下结构:
struct S
{
A a;
};
是否存在sizeof(S)
大于sizeof(A)
的情况?
例如,sizeof(std::array<T, n>)
可以大于sizeof(T[n])
吗?
能够在S中使用A意味着编译器已经了解了A的结构,并且已经向其添加了填充字节。我认为它没有理由向S添加更多的填充,因为它已经对齐了。
虽然结构可以填充,但在我所知道的所有系统上,编译器都会填充,使结构的对齐方式与其成员的最大对齐方式相同。它这样做是为了使结构的数组始终正确对齐。
因此:
struct S
{
char a;
} // Size 1, no padding
struct S2
{
unsigned int a;
char b;
} // Size 8, 3 bytes padding (assuming 32 bit integer)
编辑:请注意,编译器还可以添加内部填充,以保持数据的正确对齐。
C/C++标准没有指定任何这些细节。您想要的是运行系统的C ABI(应用程序二进制接口(,它应该指定结构的默认布局(编译器可以选择覆盖它,如果他们认为合适的话,另请参阅#pragma pack(。例如,请参阅X86_64 ABI第13页,其中指出:
骨料和工会结构和工会假设他们最严格的组成部分。每个成员都被分配到具有适当对准的最低可用偏移。尺寸任何对象的对齐总是该对象对齐的倍数。数组除了局部或全局长度至少为16字节或C99可变长度的数组变量数组变量始终具有至少16个字节的对齐。结构和并集对象可能需要填充以满足大小和对齐要求约束。任何填充的内容都是不确定的。
相关文本为5.3.3/2"应用于类时,结果是该类对象中的字节数,包括在数组中放置该类型对象所需的任何填充。">
允许一个实现添加额外的字节用于数组绑定检查(例如"this is the 5th array member out of a total of 12"
,因为这在这里允许的余地内,并且没有被任何其他要求明确禁止
(据推测,该实现还将为不属于数组的结构存储"1选1"指示;在C++中,类型S
和S[1]
是完全可交换的(
ISO/IEC 14882(10/2008(1.8.5:
除非是位字段(9.6(,否则派生最多的对象应具有非零大小,并应占据一个或多个字节的存储。基类子对象的大小可能为零。
这意味着空结构的大小为1,尽管"所有数据成员"(没有(的大小为零,零长度的位字段也是如此(不过,根据9.6.2,这必须是未命名位字段(
但两者都不适用,因为您没有要求一个空的结构,并且您的成员是命名的(所以它不能为零长度(。
如果您的a
成员的类型为void
,则情况类似,但3.9.5不允许("[…]void类型是不完整类型(3.9.1(。对象不应定义为具有不完整类型">(。
简而言之,正如你所说,你最感兴趣的是标准中所说的:不,标准没有明确定义这种情况。
然而,它也不禁止编译器添加填充或应用对齐,大多数编译器默认情况下会将结构填充/对齐到机器字大小(除非另有明确说明(。
结构可以被填充(编译器可以做任何他们喜欢的事情,例如将六个八位字节的类型填充到八个以与页面边界对齐(。不过这不太可能发生。
如果A是一个字节,则结构将与最近的边界对齐。相反,如果A小于边界,那么是的,它会更大。EX RGB的结构与RGBA的结构大小相同。
我没有可以做到这一点的示例代码。你必须转储内存并查看漏洞。如果你假设所有东西都是大小对齐的,并将一个结构投射到一堆内存中,那么你就会得到坏数据。这就是为什么WAD有用于对齐的填充。随着你的作文变得越来越复杂,编译器关闭漏洞的能力就会减弱。最终会引入填充,任何对内存布局的假设都会变得越来越错误。
- 使用结构成员指针在C++中填充结构
- C++:使用缓冲区中的数据填充结构
- 用二进制文件填充结构
- 如何使用文件填充结构(下面附有的代码)?
- 使用 snprintf 填充结构
- 使用来自函数的指针填充结构数组
- 使用循环填充结构
- C 从文件中填充结构数组
- C 如何从UCHAR数组中填充结构的位字段
- 如何有效地用向量填充结构
- 避免在C 中填充结构
- 如何填充结构的向量
- C/C++ 从字符缓冲区读取以填充结构
- 从 std::vector<无符号字符中的数据填充结构>
- 从矢量中擦除元素,并向量填充结构
- 结构错误的构造函数(调用类的构造函数 denconstructor,用于填充结构)
- 有没有办法用较短的代码来填充结构
- 填充结构,同时查找min_element,C++
- 在函数中填充结构映射的最好方法是什么?
- 当编译器决定填充结构时