是否存在“int”会导致struct padding的环境?

时间:2017-09-04 12:49:42

标签: c++ memory int alignment

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

  

记忆消耗明智,使用struct两个int的内存是否有可能比仅仅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 为了澄清,我在这里所指的是以一些有意义的数量开发和生产的系统(和编译器),特别是不是为了证明这一点而构建的理论示例,或一次性原型或爱好者创作。

5 个答案:

答案 0 :(得分:17)

  

是否有任何合理的(不一定是常见的或最新的)环境,这个小程序会打印得更大?

不是我知道的。我知道not completely reassuring,但我有理由相信,由于C ++标准的要求,没有这样的环境。

在符合标准的†编译器中,如下所示:

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

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

这意味着在给定的结构中,第二个成员将始终正确对齐 - 无论int的大小和对齐 - 如果放置在第一个成员之后,即不需要填充填充。在此布局下,struct的大小也已经是其对齐的倍数,因此也不需要尾随填充。

我们可以选择不符合标准的(大小,对齐)值,这使得此结构需要任何形式的填充。

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

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

†一个编译器 - 即使是一个不符合标准的编译器 - 可以解决任何这些错误,这可能是错误的,所以我会忽略它们。

‡我想在数组和结构都是原语的环境中,可能存在一些基本的区别,它们允许我们使用无填充数组和填充结构,但同样,我使用了don't know of any such thing

答案 1 :(得分:3)

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

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

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

我从未亲自使用过这样的实现,因此我不知道它们是否确实产生了这样的填充。但是这样做的实现是合理的,并且至少非常接近现有的实际实现。

答案 2 :(得分:2)

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

  

内存消耗明智,是否有可能使用结构   两个整数比两个整数占用更多的内存?

答案是有点......是的:

struct S
{
    int a;
    int b;

    virtual ~S() = default;
};

讽刺地指出C ++没有结构,它有类。 struct是一个引入类的声明/定义的关键字。

答案 3 :(得分:2)

只能访问64位块内存的系统可能有一个选项可以使用32位&#34; int&#34;并不是完全不可信的。与可能被uint32_t绊倒的其他程序兼容的大小提升为更大的类型。在这样的系统上,一个偶数个&#34; int&#34;值可能没有额外的填充,但具有奇数个值的值可能会这样做。

从实际角度来看,具有两个int值的结构需要填充的唯一方法是,如果结构的对齐多于两倍于&#34; int&#的粗略结果34 ;.这反过来要求结构的对齐比64位粗,或者int的大小小于32位。后一种情况本身并不常见,但是将两者结合起来会使结构对齐比int对齐粗两倍以上似乎非常奇怪。

答案 4 :(得分:0)

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