是否有任何环境会导致"int"结构填充?

Is there any environment where "int" would cause struct padding?

本文关键字:int 结构 填充 任何 环境 是否      更新时间:2023-10-16

具体来说,这出现在一个讨论中:

在内存消耗方面,使用两个intstruct是否有可能比两个int占用更多的内存?

或者,用语言术语来说:

#include <iostream>
struct S { int a, b; };
int main() {
std::cout << (sizeof(S) > sizeof(int) * 2 ? "bigger" : "the same") << std::endl;
}

这个小程序是否有任何合理的1(不一定是通用或当前)环境可以打印bigger

1澄清一下,我这里的意思是开发和生产的系统(和编译器)以某种有意义的数量,特别是不是仅仅为了证明这一点而构建的理论示例,或者一次性原型或业余爱好者的创作。

是否有任何合理的(不一定是通用或当前)环境,这个小程序会打印得更大?

不是我知道的。我知道这并不完全令人放心,但我有理由相信,由于C++标准的要求,没有这样的环境。

在符合标准的编译器中†以下编译器保存:

  • (1) 数组不能在元素之间有任何填充,因为它们可以通过指针ref访问;
  • (2)标准布局结构在每个成员之后可能有也可能没有填充,但不是在开头,因为它们与"更短"但相等的标准布局结构参考文献布局兼容;
  • (3)数组元素和结构体成员正确对齐ref;

从 (1) 和 (3) 可以看出,类型的对齐方式小于或等于其大小。如果它更大,数组将需要添加填充以使其所有元素对齐。出于同样的原因,类型的大小始终是其对齐方式的整数倍。

这意味着在给定的结构中,如果紧跟在第一个成员之后,则无论整数的大小和对齐方式如何,则第二个成员将始终正确对齐,即不需要间隙填充。在这种布局下,结构的大小也已经是其对齐方式的倍数,因此也不需要尾随填充。

我们没有一组符合标准的(大小、对齐方式)值可供选择,这使得这种结构需要任何形式的填充。

然后,任何此类填充都需要不同的目的。然而,这样的目的似乎难以捉摸。假设有一个环境出于某种原因需要此填充。无论填充的原因是什么,它很可能也适用于数组的情况,但从(1)我们知道它不能。

但是假设这样的环境确实存在,我们想要一个C++编译器。它可以通过简单地使整数变大,即通过将填充放在整数中来支持数组这种额外的必需填充。这反过来又允许结构与两个整数的大小相同,让我们没有理由添加填充。


† 一个编译器——即使是一个不符合标准的编译器——如果出现这些错误中的任何一个,也可以说是有缺陷的,所以我会忽略这些。

&ddagger; 我想在数组和结构是基元的环境中,可能存在一些潜在的区别,允许我们拥有未填充的数组和填充的结构,但同样,我不知道有任何这样的东西在使用中。

在您的具体示例中,struct S { int a, b; };,我看不到任何合理的填充论据。int应该已经自然对齐,如果是,int *可以而且应该是指针的自然表示,并且S *不需要有任何不同。但总的来说:

一些罕见的系统具有具有不同表示形式的指针,例如int *仅表示为表示"字"地址的整数,char *是字地址和该字的字节偏移量的组合(其中字节偏移量存储在单词地址的其他不需要的高位中)。取消引用char *在软件中通过加载单词,然后屏蔽和移动以获得正确的字节来实现。

在此类实现中,确保所有结构类型具有最小对齐可能是有意义的,即使结构的成员不需要这样做,只是为了指向该结构的指针不需要字节偏移混乱。这意味着给定struct S { char a, b; };sizeof(S) > 2是合理的。具体来说,我希望sizeof(S) == sizeof(int).

我个人从未使用过这样的实现,所以我不知道他们是否确实产生了这样的填充。但是这样做的实现将是合理的,并且至少非常接近现有的实际实现。

我知道这不是你要求的,这不是你问题的精神(因为你可能有标准的布局类),但严格回答这部分:

记忆消耗方面,是否有可能使用 两个整数比两个整数占用更多的内存?

答案是有点...是的:

struct S
{
int a;
int b;
virtual ~S() = default;
};

迂腐的注意是C++没有结构,它有类。struct是一个关键字,用于引入类的声明/定义。

一个只能访问 64 位块内存的系统可以选择使用 32 位"int"大小,以便与其他程序兼容,这些程序可能会被绊倒uint32_t提升到更大的类型,这并非完全不可信。 在这样的系统上,具有偶数个"int"值的结构可能没有额外的填充,但具有奇数个值的结构可能会合理地这样做。

从实际的角度来看,具有两个 int 值的结构需要填充的唯一方法是结构的对齐方式是"int"的粗略两倍以上。 这反过来又要求结构的对齐比 64 位粗,或者 int 的大小小于 32 位。 后一种情况本身并不罕见,但是以一种使结构对齐粗糙两倍以上的方式组合两者似乎非常奇怪。

理论上,填充用于提供访问内存区域的有效方法。如果向 2 个整数变量添加填充会比 yes 提高效率,它可以有填充。但实际上我没有遇到任何带有 2 个整数有填充位的结构。