为什么struct中的double成员没有在8字节边界上对齐?

时间:2013-02-15 11:33:40

标签: c alignment

这是关于内存对齐的。在下面的代码中,我预计结构中b的偏移量为8(32位机器)。见here。在那里,使b始终出现在缓存行中。但事实并非如此。 b全局对象中的成员struct test1似乎已对齐。我不确定它是偶然的还是编译器是故意这样做的。

我想了解为什么编译器在a之后没有填充4个字节。

struct test1
{
int a;
double b;
}t1;

int main()
{
struct test1 *p = malloc(sizeof(struct test1));
printf("sizes int %d, float %d, double %d, long double %d\n", sizeof(int), sizeof(float), sizeof(double), sizeof(long double));
printf("offset of b %d\n",(int)&(t1.b)-(int)&(t1));

printf("\naddress of b (on heap) = %p, addr of b (on data seg) = %p\n",&(p->b), &(t1.b));

return 0;
}

输出是......

sizes int 4, float 4, double 8, long double 12
offset of b 4

address of b (on heap) = 0x804a07c, addr of b (on data seg) = 0x80497e0

我在ubuntu 10.04上使用标准的gcc编译器

3 个答案:

答案 0 :(得分:5)

根据System V ABI for i386,第28页,double只能获得4个字节的对齐,但建议编译器提供8个字节的选项。看来这是GCC在Linux上实现的,该选项被称为-malign-double

另一种方法是使用-m64来获取x86-64目标代码,这在某些系统上已经是默认设置,包括Mac OS X.

答案 1 :(得分:4)

  

我预计结构中b的偏移量为8(32位机器)。见这里

您的参考资料解释了为什么8对齐双打可能有利。这并不等于保证,双精度始终是8对齐的。如果你的消息来源说他们总是8对齐,并且你观察到他们不是的实现,那么你的消息来源是错误的。

来自GCC手册页:

  

对齐   双字边​​界上的“双”变量将产生代码   奔腾上的运行速度稍慢,代价是更多的内存。

因此,GCC声明4对齐的原因是为了节省内存。您可以使用-malign-double-mno-align-double来控制它,但是如果您在使用冲突选项编译的代码之间共享结构,那么您当然会面临创建二进制不兼容的风险。对于特定的对象/结构成员,您可以使用GCC自己的__attribute__((aligned))_Alignas(在C11中)或alignas(在C ++ 11中),所有这些都可以使用整数常量来指定所需的对齐。

答案 2 :(得分:0)

在ANSI C中根本无法保证对齐。

对齐自动变量比在堆上声明的任何内容更多。如果您使用的是POSIX OS,请使用memalign(3)接收您确定已对齐的内存。 Malloc可以在任何偏移处返回内存。您可以使用__attribute__ ((__packed__))之类的编译器指令来放置自己的路线。