为什么对齐long long union成员比包含union/struct更大?它是否正确?

Pio*_*ycz 8 c++ g++ memory-alignment unsigned-long-long-int unions

这个问题开始,人们可以开始相信联盟的一致性不低于其个体成员的最大一致性.但我对long longgcc/g ++中的类型有问题.完整的示例可以在这里找到,但这里是我的问题的相关部分:

union ull {
  long long m;
};

struct sll {
  long long m;
};


int main() {
#define pr(v) cout << #v ": " << (v) << endl
   pr(sizeof(long long));
   pr(__alignof__(long long));
   pr(sizeof(ull));
   pr(__alignof__(ull));
   pr(sizeof(sll));
   pr(__alignof__(sll));
};
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

sizeof(long long): 8
__alignof__(long long): 8
sizeof(ull): 8
__alignof__(ull): 4
sizeof(sll): 8
__alignof__(sll): 4
Run Code Online (Sandbox Code Playgroud)

为什么union成员的对齐大于包含union的对齐?

[UPDATE]

根据基思的回答,对齐在这里是错误的.但我测试了以下内容,似乎alignof 告诉我们真实情况.看到:

union ull {
  long long m;
};
long long a;
char b;
long long c;
char d;
ull e;
int main() {
#define pr(v) cout << #v ": " << (v) << endl
   pr(size_t((void*)&b));
   pr(size_t((void*)&c));
   pr(size_t((void*)&d));
   pr(size_t((void*)&e));
   pr(size_t((void*)&c) - size_t((void*)&b));
   pr(size_t((void*)&e) - size_t((void*)&d));
};
Run Code Online (Sandbox Code Playgroud)

输出:

size_t((void*)&b): 134523840
size_t((void*)&c): 134523848
size_t((void*)&d): 134523856
size_t((void*)&e): 134523860
size_t((void*)&c) - size_t((void*)&b): 8
size_t((void*)&e) - size_t((void*)&d): 4
Run Code Online (Sandbox Code Playgroud)

因此,全局数据中的对齐long long为8,并且包含的​​对齐long long为4.对于本地范围,我无法测试这个,因为似乎编译器可以自由重新排列本地数据 - 所以这个技巧不起作用.你能评论一下吗?

[/ UPDATE]

Kei*_*son 7

__alignof__(这是gcc扩展名)不一定报告类型所需的对齐方式.

例如,对于任何类型,x86处理器实际上不需要超过1字节的对齐.如果对象是字对齐的,则访问4字节或8字节对象可能会更有效,但字节对齐就足够了.

引用gcc文档:

有些机器实际上从不需要对齐; 即使在奇数地址,它们也允许引用任何数据类型.对于这些机器, __alignof__报告GCC将给出数据类型的最小对齐,通常由目标ABI强制执行.

但这仍然没有真正回答这个问题.即使有这个松散​​的定义,我也没有想到任何有理由__alignof__表明long long比包含a的结构或联合更严格的对齐long long.

确定类型对齐的更便携方法是:

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t)))
Run Code Online (Sandbox Code Playgroud)

这会产生t由a char和a 组成的结构中类型成员的偏移量t.使用这个宏,这个程序:

#include <iostream>
#include <cstddef>

union ull {
  long long m;
};

struct sll {
  long long m;
};

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t)))

int main() {
#define pr(v) std::cout << #v ": " << (v) << std::endl
   pr(sizeof(long long));
   pr(__alignof__(long long));
   pr(ALIGNOF(long long));
   pr(sizeof(ull));
   pr(__alignof__(ull));
   pr(ALIGNOF(ull));
   pr(sizeof(sll));
   pr(__alignof__(sll));
   pr(ALIGNOF(sll));
};
Run Code Online (Sandbox Code Playgroud)

在我的系统上生成此输出(gcc-4.7,Ubuntu 12.04,x86):

sizeof(long long): 8
__alignof__(long long): 8
ALIGNOF(long long): 4
sizeof(ull): 8
__alignof__(ull): 4
ALIGNOF(ull): 4
sizeof(sll): 8
__alignof__(sll): 4
ALIGNOF(sll): 4
Run Code Online (Sandbox Code Playgroud)

我的ALIGNOF()宏指示的结果是一致的:long long具有4字节对齐,以及包含long long4字节对齐的结构或联合.

我怀疑这是一个bug,或者至少是一个不一致的,在gcc的实现中__alignof__.但是定义的模糊性使得很难确定它真的是一个错误.似乎没有报道.

更新:

我可能会开枪,但我刚刚提交了一份错误报告.

这个早期的错误报告,关闭为"INVALID",类似,但它并不是指结构本身的对齐方式.

更新2:

我的错误报告已作为早期错误报告的副本关闭.我会要求澄清.