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

时间:2012-08-06 08:48:28

标签: c++ g++ memory-alignment unions unsigned-long-long-int

this question开始,人们可以开始相信联盟的对齐不小于其个人成员的最大对齐。但我对gcc / g ++中的long long类型有疑问。可以找到完整的示例here,但这里是我的问题的相关部分:

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));
};

这导致以下输出:

sizeof(long long): 8
__alignof__(long long): 8
sizeof(ull): 8
__alignof__(ull): 4
sizeof(sll): 8
__alignof__(sll): 4

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

[UPDATE]

根据基思的回答 alignof 在这里是错误的。但我测试了以下内容,似乎 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));
};

输出:

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

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

[/ UPDATE]

1 个答案:

答案 0 :(得分:7)

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

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

引用gcc documentation

  

有些机器实际上从不需要对齐;他们允许参考   甚至在奇数地址的任何数据类型。对于这些机器,   __alignof__报告了GCC给出的最小一致性   数据类型,通常由目标ABI强制执行。

但这仍然没有真正回答这个问题。即使有那么宽松的定义,我也没有想到__alignof__指出long long的更严格的对齐比包含long long的结构或联合更好的理由。

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

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

这会在由tchar组成的结构中产生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));
};

在我的系统上生成此输出(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

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

我怀疑在gcc的__alignof__实现中这是一个错误,或者至少是一个不一致的错误。但是定义的模糊性使得很难确定它真的是一个错误。 It doesn't seem to have been reported

更新:

我可能会开枪,但我刚刚提交了bug report

earlier bug report,关闭为“INVALID”,类似,但它不是指结构本身的对齐方式。

更新2:

我的错误报告已作为前一个报告的副本关闭。我会要求澄清。