结构的大小会受到数组元数据的影响吗?

Can sizeof of struct be affected by array metadata?

本文关键字:元数据 影响 数组 结构      更新时间:2023-10-16

关于structsizeof(不)等于其元素sizeof之和,已经存在许多问题。通常这是由于数据对齐。这个问题数据对齐无关,因此请假设所有类型的大小都是对齐的倍数(例如 4B)。

如此处所述,分配数组将导致存储一些元数据,其大小与分配的数组大小相当。假设我们有以下代码:

const int size = 10;
struct X {
int someInt;
int array[size];
};
struct Y {
int someInt;
T array[size];
};

由于size在编译时是已知的,因此编译器应该足够聪明,以确定在X的情况下不需要存储任何元数据。即使在Y的情况下,编译器也可以足够聪明地遵循这种推理(这里可能存在 C 和 C++ 之间的差异,因为C++中还有为T的单个实例调用析构函数的额外要求)。

我的问题是:我能保证sizeof(X) == (size + 1) * sizeof(int)还是特定于编译器?或者更一般地说,是sizeof(Y) == size * sizeof(T) + sizeof(int)


编辑:希望澄清一点:问题是关于C和C++的。问这个问题的最初动机也是这样的。如果我跑

X *foo = new X[100];

或者它在代码中的某个地方是 C 等效的,它会创建一个大小100 * (size + 1) * sizeof(int)的连续内存块吗?

常见实现中的 C 数组不会在其周围存储任何元数据,但是,可以将填充添加到结构中,以便a_struct_ptr + 1有足够的对齐方式进行a_struct

在第一个结构({ int someInt; int array[size]; })的情况下,不需要填充,所以

sizeof(X) == (size + 1) * sizeof(int)

应该成立(虽然,我认为编译器没有义务保证它)。

对于第二个结构,Tint的对齐要求可能会导致向结构中添加填充,从而使公式无效。

元数据可以隐藏在struct成员之间。 我从未见过元数据的这种用途,但编译器可以在一定程度上使用类型的对齐方式,通过强制int的对齐大于 4 个字节等int宽度,在两个int成员之间提供不连续的内存。 如果编译器将其用于元数据、性能填充或恶意,则无关紧要。 关键是它可能存在。

C99/C11 提供max_align_t,因此类型本身不会超过根据 C 规范的对齐方式。

基本对齐由

小于或等于实现在所有上下文中支持的最大对齐的对齐表示,该对齐等于_Alignof (max_align_t)。 §6.2.811dr §6.2.8 2

max_align_t这是一种对象类型,其对齐方式与所有上下文中的实现所支持的对齐方式一样大; §7.19 2

因此,任何小于max_align_t的结构成员都会在潜在上下文中受到填充/元数据的影响。