为什么在X86和arm中使用类似版本的gcc计算相同结构的大小是不同的?

时间:2013-05-26 13:39:51

标签: c linux gcc arm visual-c++

正如主题所说,我得到了计算相同结构的相同操作的不同结果。结构如下。

struct test
{
  char m1;
  double d1;
}

当使用sizeof(struct test)在gcc-4.6.3和linux中的gcc-4.2中计算它时,我得到了结果“12”。虽然我在Linux中使用gcc-4.6.1而在WinXP中使用VC 6.0,但我得到了结果“16”。所以我很困惑,为什么会这样呢? GCC如何计算结构的大小?

加入:

正如答案所说,arm linux需要8字节对齐AAPCS定义,但为什么x86中的vc 6.0获得结果“16”?有人使用vc 2003或更高版本来计算吗?

C标准如C89 / C99还有什么定义呢?

2 个答案:

答案 0 :(得分:5)

double总是8个字节长,但对齐要求因架构而异。在ARM中(显然,从您的示例中),要求是在8字节边界上对齐双精度。

结构总是用空格填充,使其大小为具有最大对齐要求的字段的倍数。在上面的例子中,编译器将放入m1,然后是3(或7)个填充字节,然后是d1。

只是令人困惑,在x86上,对齐只需要4字节边界,但GCC可以选择使其成为8字节边界以提高性能。从gcc手册页:

-malign双

-mno对准双

控制GCC是否在双字边界或一个字边界上对齐双长,长双和长长变量。在双字边界上对齐双变量将产生在“奔腾”上运行得更快的代码,代价是更多的内存。 警告:如果使用-malign-double开关,则包含上述类型的结构将与386的已发布应用程序二进制接口规范的对齐方式不同,并且与不使用该开关编译的代码中的结构不兼容。

答案 1 :(得分:2)

补充Dave-B's answer

gcc changes包含有关ABI更改的注释,以便在 8字节边界上对齐大于 8字节的向量。 ARM AAPCS的表4.1给出了对齐文档,

  

过程调用ARM体系结构的标准
   4.1基本数据类型
  类型类别字节大小字节对齐
  积分无符号8 8
  双字
  浮动双8 8   点精度

这通常是有利的,因为数据不会跨越高速缓存行。此外,如果内存对齐,ARM ldrd and strd会更快。由于这是 C 编译器ARM标准的一部分,因此编译器的互操作性gcc应该默认执行此操作。使用attribute(packed)并优化尺寸-Os 可能会更改对齐方式。

许多ARM处理器上使用的internal bus是64位。

另请参阅:ARM C calling convention