1

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

struct test
{
  char m1;
  double d1;
}

在 linux 的 gcc-4.6.3 和 gcc-4.2 中使用 sizeof(struct test) 计算时,我得到的结果是“12”。当我在 linux 中使用 gcc-4.6.1 和在 WinXP 中使用 VC 6.0 时,我得到了结果“16”。所以我很困惑,为什么会发生这种情况?GCC 如何计算结构的大小?

添加:

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

C89/C99等C标准还定义了什么?

4

2 回答 2

6

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

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

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

-malign-double

-mno-align-double

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

于 2013-05-26T14:18:32.697 回答
2

为了补充Dave-B 的回答

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

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

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

许多 ARM 处理器上使用的内部总线是 64 位的。

另请参阅:ARM C 调用约定

于 2013-05-26T14:56:33.013 回答