指定64位对齐

rwa*_*ace 12 c++ gcc alignment

给定一个结构定义

struct foo {
    int a, b, c;
};
Run Code Online (Sandbox Code Playgroud)

什么是最好的(最简单,最可靠和最便携)方式来指定它应该始终与64位地址对齐,即使在32位构建上也是如此?我正在使用C++ 11和GCC 4.5.2,并希望也支持Clang.

小智 15

既然你说你正在使用GCC并希望支持Clang,那么GCC的aligned 属性应该可以解决问题:

struct foo {
    int a, b, c;
} __attribute__((__aligned__(8))); // aligned to 8-byte (64-bit) boundary
Run Code Online (Sandbox Code Playgroud)

  • @JohnDibling:我知道.它可以移植到有问题的两个编译器中. (2认同)

Ste*_*sop 7

以下是相当便携的,因为它可以在很多不同的实现上工作,但不是全部:

union foo {
    struct {int a, b, c; } data;
    double padding1;
    long long padding2;
};

static char assert_foo_size[sizeof(foo) % 8 == 0 ? 1 : -1];
Run Code Online (Sandbox Code Playgroud)

除非有以下情况,否则无法编译:

  • 编译器添加了一些填充以foo使其达到8的倍数,这通常只是出于对齐要求而发生,或者
  • 布局foo.data非常奇怪,或者
  • 其中一个long longdouble大于3个整数,以及8的倍数.这并不一定意味着它是8对齐的.

鉴于你只需要支持2个编译器,并且clang在设计上是相当gcc兼容的,只需使用__attribute__它.如果你现在想要编写代码,那么只考虑做其他任何事情(希望)可以在你没有测试的编译器上工作.

C++ 11添加了alignof,您可以测试而不是测试大小.它将删除误报,但仍然留下一些符合实现的联合无法创建所需的对齐,因此无法编译.另外,我的sizeof诀窍是非常有限的,如果你的结构有4个整数而不是只有3个,它根本无济于事,而同样的东西alignof也是如此.我不知道gcc和clang支持的版本是什么alignof,这就是我没有用它开始的原因.我不会想到这很难.

顺便说一句,如果foo动态分配实例,那么事情会变得更容易.首先,我怀疑glibc或类似的malloc实现无论如何都会8对齐 - 如果有一个8字节对齐的基本类型,那么malloc我认为glibc malloc总是这样,而不是担心是否存在任何问题给定平台.其次,这posix_memalign是肯定的.


Wak*_*Leo 5

你应该使用__attribute__((aligned(8)). 但是,我发现此描述仅确保分配的结构大小是 8 字节的倍数。它不确保起始地址是倍数。

例如。我使用__attribute__((aligned(64)),malloc可能会返回一个64Byte长度的结构体,其起始地址为0xed2030。

如果你希望起始地址对齐,你应该使用aligned_alloc: gcc对齐分配aligned_alloc(64, sizeof(foo)将返回 0xed2040。