结构的 sizeof 会受数组元数据的影响吗?

Posted

技术标签:

【中文标题】结构的 sizeof 会受数组元数据的影响吗?【英文标题】:Can sizeof of struct be affected by array metadata? 【发布时间】:2017-04-04 19:52:50 【问题描述】:

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

正如here 所解释的,分配一个数组将导致一些元数据被存储在所分配数组的大小左右。假设我们有以下代码:

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) 的内存块吗?

【问题讨论】:

您不会以需要任何元数据的方式“分配”任何数组。 没有元数据。这些是数组而不是 std::vectors。 您的链接说明是动态分配的,您的情况没有元数据。 链接中的文字是在讨论动态分配new [] C:抛开对齐/包装问题。 sizeof(Y) == size * sizeof(T) + sizeof(int) 是真的。如果存在某种形式的 mettadata,它不会对sizeof 有贡献,也不会存在于someIntarray 之间。然而为什么这很重要?依赖此功能的代码尝试是什么? 【参考方案1】:

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

对于第一个结构体( int someInt; int array[size]; ),应该不需要填充,所以

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

应该成立(不过,我认为编译器没有义务保证这一点)。

在第二个结构的情况下,Tint 的对齐要求可能会导致向结构添加填充,这会使您的等式无效。

【讨论】:

“C 数组不存储任何元数据”嗯。当然 C 没有指定任何元数据。编译器可以以某种方式存储每个对象的元数据。问题是:这种添加的数据是否允许在struct 的成员之间存在?国际海事组织:没有。 我认为这是编译器“不存储元数据”的经验观察。如果他们这样做了,它将与类型相关联,而不是与类型的变量相关联——有点像 C++ 中的 v-tables。在编译器应用的填充中,最多可能有一个指向结构尾部某处的指针。但这不太可能是一个实际问题。是的,理论上,编译器可以将信息添加到结构中。不,实际上,编译器不会这样做,因为没有必要/没有好处。 可以很好地添加填充,例如 64 位对齐甚至更宽的缓存行对齐。 @JonathanLeffler 嗯,我想如果编译器想在结构成员之间添加一些 MD,它可以使 max_align_t 非常宽并将其隐藏在填充中,除了相邻的 max_align_t 成员。不过,不清楚为什么这对 OP 很重要。 我有一种感觉,OP 指的是元数据,它是语言的一部分。这是因为他写道它不应该在那里,因为数组的大小是已知的。并且还了解某些事情可能是编译器特定的(问题的最后一行)。他问这是否是特定于编译的这一事实清楚地表明他不是在谈论特定于实现的 md。我认为我们对这个问题的了解太多了。【参考方案2】:

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

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 的结构成员都受制于潜在上下文中的填充/元数据

【讨论】:

以上是关于结构的 sizeof 会受数组元数据的影响吗?的主要内容,如果未能解决你的问题,请参考以下文章

在笛卡尔积中,元数与元组个数是相同的意思吗

四旋翼飞控里 为啥一定要用四元数?用欧拉角不一样吗? 就算用四元数也是将四元数转化为欧拉角进

使用object-sizeof依赖项会对内存产生什么影响

石英表会受磁吗

将元数据传递给自定义损失函数

std::tuple sizeof,是错过了优化吗?