可以在结构中包装类型会导致额外的填充吗?

时间:2011-09-01 11:01:09

标签: c++ arrays class struct padding

  

可能重复:
  Size of struct with a single element

给定任何类型A和以下结构:

struct S
{
    A a;
};

是否有sizeof(S)大于sizeof(A)的情况?

例如,sizeof(std::array<T, n>)可以大于sizeof(T[n])吗?

6 个答案:

答案 0 :(得分:5)

能够在S内部使用A意味着编译器已经知道A的结构并且已经添加了填充字节。我认为没有理由为S添加更多填充,因为它已经对齐。

答案 1 :(得分:3)

虽然结构可以填充,但在我知道的所有系统上,编译器将填充以使结构的对齐与其成员的最大对齐相同。它这样做是为了使结构的数组始终正确对齐。

所以:

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个字节的对齐方式。结构体   和union对象可能需要填充以满足大小和对齐   限制。任何填充的内容都是未定义的。

答案 2 :(得分:2)

相关文本是5.3.3 / 2“当应用于类时,结果是该类对象中的字节数,包括在数组中放置该类型对象所需的任何填充。”

允许实现为数组绑定检查添加额外的字节(例如"this is the 5th array member out of a total of 12",因为这是在此处授予的余地内,并未明确禁止任何其他要求。

(据推测,该实现还会为不属于数组的结构存储“1 of of 1”指示;在C ++中,SS[1]类型可以完全互换。 / p>

答案 3 :(得分:1)

ISO / IEC 14882(10/2008)1.8.5

  

除非它是位字段(9.6),否则最派生的对象应具有非零大小并且应占用一个或多个   存储字节。基类子对象的大小可以为零。

这意味着 empty 结构的大小为1,尽管“所有数据成员”(没有)的大小为零,零长度位域也是如此(根据9.6。 2但这必须是未命名的位域。) 虽然没有真正适用,因为你没有要求一个空的结构,并且你的成员命名(所以它不能是零长度)。

如果您的a成员属于void类型,但 3.9.5 不允许(“[...] void类型是不完整类型(3.9.1)。对象不应被定义为具有不完整类型“)。

简而言之,正如您所说,您对标准所说的内容最感兴趣:不,标准没有明确定义这样的情况。

但是,它也不禁止编译器添加填充或应用对齐,并且大多数编译器默认将结构填充/对齐到机器字大小(除非另有明确说明)。

答案 4 :(得分:0)

如果A是一个字节,那么struct将与最近的边界对齐。相反,如果A小于边界,那么它将更大。 EX的RGB结构与RGBA的结构大小相同。

我没有可以执行此操作的示例代码。你必须转储内存并看到漏洞。如果你假设所有东西都是大小对齐的并且将结构转换成一堆内存,那么你将得到错误的数据。这就是为什么WAD有填充对齐的原因。随着组合变得越来越复杂,编译器关闭孔的能力就会降低。最终将引入填充,并且对内存布局的任何假设都将变得越来越错误。

答案 5 :(得分:0)

结构可以填充(允许编译器做任何他们喜欢的事情,例如将六个八位字节类型填充到八个以与页面边界对齐)。但这不太可能发生。

std :: array 更大,因为它在类中存储了一些额外的信息,比如数组的长度。在自动导频上键入;不假思索地阅读std :: vector。