是否有任何环境会导致"int"结构填充?
Is there any environment where "int" would cause struct padding?
具体来说,这出现在一个讨论中:
在内存消耗方面,使用两个
int
的struct
是否有可能比两个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++编译器。它可以通过简单地使整数变大,即通过将填充放在整数中来支持数组中这种额外的必需填充。这反过来又允许结构与两个整数的大小相同,让我们没有理由添加填充。
† 一个编译器——即使是一个不符合标准的编译器——如果出现这些错误中的任何一个,也可以说是有缺陷的,所以我会忽略这些。
‡ 我想在数组和结构是基元的环境中,可能存在一些潜在的区别,允许我们拥有未填充的数组和填充的结构,但同样,我不知道有任何这样的东西在使用中。
在您的具体示例中,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 个整数有填充位的结构。
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- 编译器指出结构和 int 说明的错误 2059
- C++ std::vector<int> 体系结构的未定义符号 x86_64:
- 对结构int成员进行排序
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 为什么我不能将 int 分配给结构成员的联合成员?
- unordered_set是否适合存储矢量<int>元素的数据结构?如果是这样,我将如何实现哈希函数?
- 将 int 映射到 C++ 中的向量结构
- STL 对priority_queue<int、结构>错误
- 如何将来自文本文件的数据读取到结构的int阵列中
- 错误:成员引用基类型"uint32_t"(也称为"无符号 INT")不是结构或联合
- 如何从输入中定义的"external" int 定义结构中的数组大小
- 结构C++可以用 0 初始化,但不能用另一个 int 初始化
- C++ 如何从指向结构的指针将 PTR 返回到 int
- 在 UDP 套接字上发送结构、浮点数和 int C++
- 声明 Windows API 结构 (DCB) 的对象 - 错误 C4430:缺少类型说明符 - 假定为 int
- 如何在另一个结构 arrya 中的一个结构中初始化一个 int 数组
- 是一个包含两个INT(只有两个INT)的结构,保证是大小(INT)的两倍
- 带有两个INT列表的结构将减少为一个INT
- 是否有任何环境会导致"int"结构填充?