正如主题所说,我得到了计算相同结构的相同操作的不同结果。结构如下。
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还有什么定义呢?
答案 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位。