堆栈variables是否由GCC __attribute __((aligned(x)))alignment?

我有以下代码:

#include <stdio.h> int main(void) { float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0}; printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); } 

我有以下输出:

 0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac 

为什么a[0]的地址不是0x1000的倍数?

什么__attribute__((aligned(x)))呢? 我误解了这个解释?

我正在使用gcc 4.1.2。

我相信问题是你的数组在栈上。 因为堆栈指针可能是函数启动时的任何东西,所以没有办法alignment数组,而不分配比需要更多的东西并调整它。 如果将数组移出函数并将其转换为全局variables,它应该可以工作。 你可以做的另一件事是保持它作为一个局部variables(这是一件很好的事情),但使其static 。 这将防止它被存储在堆栈上。 注意这两种方式都不是线程安全的或者是recursion安全的,因为只有一个数组副本。

有了这个代码:

 #include <stdio.h> float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0}; int main(void) { printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); } 

我得到这个:

 0x804c000 0x804c004 0x804c008 0x804c00c 

这是预期的。 用你的原始代码,我只是得到像你一样的随机值。

gcc中存在一个错误,导致alignment的属性不能用于堆栈variables。 它似乎是修补与下面链接的补丁。 下面的链接也包含了相当多的讨论。

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660

我已经尝试了上面的两个不同版本的gcc:4.1.2从一个RedHat 5.7框,你的问题类似于你的问题(本地arrays没有任何alignment的0x1000字节边界)。 然后,我在RedHat 6.3上用gcc 4.4.6试了一下你的代码,它工作得很好(本地数组是alignment的)。 神话电视人也有类似的问题(上面的海湾合作委员会补丁似乎修复):

http://code.mythtv.org/trac/ticket/6535

无论如何,它看起来像你在gcc中发现一个错误,似乎在更高版本中修复。

最近的GCC(使用4.5.2-8ubuntu4进行testing)似乎可以正常工作,arrays正确alignment。

 #include <stdio.h> int main(void) { float a[4] = { 1.0, 2.0, 3.0, 4.0 }; float b[4] __attribute__((aligned(0x1000))) = { 1.0, 2.0, 3.0, 4.0 }; float c[4] __attribute__((aligned(0x10000))) = { 1.0, 2.0, 3.0, 4.0 }; printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); printf("%p %p %p %p\n", &b[0], &b[1], &b[2], &b[3]); printf("%p %p %p %p\n", &c[0], &c[1], &c[2], &c[3]); } 

我得到:

 0x7ffffffefff0 0x7ffffffefff4 0x7ffffffefff8 0x7ffffffefffc 0x7ffffffef000 0x7ffffffef004 0x7ffffffef008 0x7ffffffef00c 0x7ffffffe0000 0x7ffffffe0004 0x7ffffffe0008 0x7ffffffe000c 

Alignement对于所有types都是无效的。 您应该考虑使用结构来查看实际中的属性:

 #include <stdio.h> struct my_float { float number; } __attribute__((aligned(0x1000))); struct my_float a[4] = { {1.0}, {2.0}, {3.0}, {4.0} }; int main(void) { printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); } 

然后,你会看到:

 0x603000 0x604000 0x605000 0x606000 

这是你所期望的。

编辑:推@yzap和@Caleb案例评论,最初的问题是由于GCC版本 。 我已经检查了GCC 3.4.6与GCC 4.4.1与请求者的源代码:

 $ ./test_orig-3.4.6 0x7fffe217d200 0x7fffe217d204 0x7fffe217d208 0x7fffe217d20c $ ./test_orig-4.4.1 0x7fff81db9000 0x7fff81db9004 0x7fff81db9008 0x7fff81db900c 

现在很明显,较老的GCC版本(4.4.1之前的某个版本)显示alignment病理。

注1:我build议的代码并不回答我理解为“alignment数组的每个字段”的问题。

注2:在main()中引入非静态a []并使用GCC编译3.4.6打破了struct数组的alignment指令,但保持0x1000结构之间的距离…仍然不好! (请参阅@zifre解决方法的答案)