【问题标题】:alignas in structs on 32-bit platforms32 位平台上的结构中的对齐
【发布时间】:2016-04-10 14:43:45
【问题描述】:

在为 32 位 x86 linux 运行以下代码时,我得到了意想不到的结果(编译器标志:g++ -std=c++14 -m32)。我试过 gcc 和 clang。

#include <iostream>
using namespace std;

struct S1
{
  uint64_t a;
  uint32_t b;
};

struct S2
{
  alignas(uint64_t) char a[8];
  uint32_t b;
};

int main()
{
  cout << "sizeof(S1)=" << sizeof(S1) << endl;
  cout << "sizeof(S2)=" << sizeof(S2) << endl;
}

输出是:

sizeof(S1)=12
sizeof(S2)=16

这里发生了什么?为什么 S1 和 S2 的大小不同?据我了解,64 位整数值在 32 位 x86 机器上与 32 位对齐。这确实解释了为什么 S1 的大小是 12 字节。但是为什么这不适用于 S2?

【问题讨论】:

  • 可能缓存行对齐字符数组a 包括一个额外的 4 字节块用于使 S2 16 字节的数组?可能相关:stackoverflow.com/questions/17091382/…
  • 这不是答案,而是进步。 alignas(uint64_t) 的定义与alignas(alignof(uint64_t)) 相同。如果您将cout &lt;&lt; alignof(uint64_t) &lt;&lt; endl ; 添加到示例中,您将获得 8 的输出(至少 gcc)。所以问题应该是'为什么 gcc 认为 alignof(uint64_t) 在相关平台上为 4 时为 8。注意:它必须是 4,因为 sizeof(S1) 是 12。
  • 要查看大小差异是否与您使用char[8]这一事实有关,您能否将S2中的alignas(uint64_t) char a[8];中的alignas(uint64_t) char a[8];替换为另一个64位输入,例如double?
  • @arainone 我认为这只会混淆问题。 alignof(double) 通常是 8。所以sizeof(S2) 在没有 alignas(uint64_t) 的情况下是 16。正如我提到的 gcc 说 alignof(uint64_t) 是 8。这似乎是问题的根源。
  • 这似乎与this question有关。也可能是this thread of gcc mailing list

标签: c++ padding alignas


【解决方案1】:

alignof 关键字衡量一个类型作为一个完整对象的对齐方式;即当它被分配为单个对象或数组元素时。这不一定与该类型作为子对象的对齐要求相同; Are members of a POD-struct or standard layout type guaranteed to be aligned according to their alignment requirements?

x386 ABI 要求结构内 64 位整数的对齐方式为 4 字节; gcc 不能随意更改它,因为它会破坏与其他目标文件和程序的二进制兼容性。但是,它可以将完整对象的 64 位整数对齐到 8 个字节,因为这样做不会影响 ABI,并且可以更有效地访问内存。

【讨论】:

    猜你喜欢
    • 2012-09-01
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    相关资源
    最近更新 更多