【发布时间】:2013-01-31 08:59:58
【问题描述】:
这是关于内存对齐的。在下面的代码中,我预计结构内 b 的偏移量为 8(32 位机器)。见here。因此,使b 始终出现在缓存行中。然而,事实并非如此。 struct test1 的全局对象中的成员 b 似乎是对齐的。我不确定它是偶然还是编译器故意这样做。
我想了解为什么编译器没有在 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 编译器
【问题讨论】:
-
一方面,如果 CPU 可以处理未对齐的操作数,那就没有问题。现在,为什么您的编译器要紧密打包结构,这是一个问题。你是如何编译代码的?是否有来自 makefile 或编译器可能从其配置文件中提取的任何隐藏编译选项?
-
@Alexey,不,它只是 gcc test.c; ./a.out
-
在使用“默认”选项和 -m32 使用 gcc 4.6.3 进行编译时,我得到了相同的结果(我有一个 64 位操作系统,所以默认是 64 位,在这种情况下,它给了我一个 8 字节对齐)。
-
gcc 将 Linux x86 上的双精度对齐到 4 个字节。如果您想要 8 字节对齐,请使用 -malign-double。您链接到错误事实的问题,因为对齐是一个依赖于平台的问题,甚至 Windows 和 linux 平台在 x86 上对齐双重不同
-
这是 Unix i386 ABI。 double 需要在 4 字节边界上对齐。其他 ABI(和其他架构)可能有其他要求。