5

这是关于内存对齐的。在下面的代码中,我预计结构内 b 的偏移量为 8(32 位机器)。见这里。因此,使得b总是发生在一个高速缓存行内。然而,事实并非如此。b全局对象中的成员struct test1似乎是对齐的。我不确定它是偶然还是编译器故意这样做。

我想了解为什么编译器在a.

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 编译器

4

3 回答 3

5

According to the System V ABI for i386, page 28, double only gets 4 bytes alignment, but compilers are recommended to provide an option for 8 bytes as well. It appears this is what is implemented by GCC on Linux, the option being called -malign-double.

Another alternative is to use -m64 to get x86-64 object code, which is already the default on some systems including Mac OS X.

于 2013-02-15T14:08:18.857 回答
4

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

您的参考资料解释了为什么 8 对齐双打可能是有利的。这并不意味着双打总是8对齐的。如果您的消息来源说它们始终是 8 对齐的,而您观察到它们不是的实现,那么您的消息来源是错误的。

从 GCC 手册页:

在两个字边界上对齐“双”变量将产生在奔腾上运行得更快的代码,但会消耗更多内存。

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

于 2013-02-15T12:58:17.260 回答
0

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

与在堆上声明的任何内容相比,自动变量更容易发生对齐。如果您使用的是 POSIX 操作系统,请使用 memalign(3) 接收您确定已对齐的内存。Malloc 可以在任何偏移量处返回内存。您可以使用编译器指令__attribute__ ((__packed__)),例如放入您自己的对齐方式。

于 2013-02-15T11:47:35.577 回答