与数据结构对齐混淆?

时间:2014-02-08 07:23:16

标签: c struct padding long-double

代码1: -

struct emp
{
  char a;
  double b;
};
int main()
{
    struct emp e;
    printf("%p    %p", (void*)&e.a, (void*)&e.b);
}

我的电脑输出: -

OO28FF00    0028FF08

由于chardouble的大小分别为'1'和'8',因此0028FF000028FF08是'1'和'8的倍数'分别。

代码2: -

struct emp
{
  char a;
  long double b;
};
int main()
{
    struct emp e;
    printf("%p    %p    \n", (void*)&e.a,(void*)&e.b);
}

输出结果为: -

0028FF00    0028FF04

由于charlong double的大小分别为'1'和'12',但0028FF04不是'12'的倍数。

为什么在这种情况下不应用填充?

3 个答案:

答案 0 :(得分:3)

long double80 bit floating point所以你需要10个字节。 10虽然真的不是一个非常好的大小,因此英特尔32位处理器决定了12个字节。 12是4的倍数,表示32位(3×32位)。这被认为是对齐的,因为32位处理器仅需要4个字节对齐,因此12个字节在任何4个字节边界处对齐。显然,编译器知道它在做什么,它总是试图生成最小的可能结构。

这就是说,你可以看到你不能使用结构声明并希望将它保存在文件中...至少不能使用默认的C类型(你可以使用int32_t,uint64_t等。得到你想要的,但浮点数没有等价...)

有人评论说,在64位架构上,long double是16个字节。浪费了6个字节......但是它使得64位类型始终保持一致。

答案 1 :(得分:2)

维基百科有一个典型路线表:

x86具有灵活的内存访问指令,因此规则由编译器设计者决定。我们只能想象为什么他们认为最合理。

我发现@LưuVĩnhPhúc的评论很有教育意义。虽然long double在您的平台上是12个字节(GCC?),但是4字节对齐的原因与512字节结构不是512字节对齐的原因相同;在太空中会有太多的浪费。我想GCC的设计者认为访问double变量应该以尽可能少的延迟来完成,代价是一些空间(最多7个字节)。

答案 2 :(得分:0)

嗯,据我所知,填充和数据对齐在很大程度上取决于目标体系结构,编译器优化选项和优化器的整体质量。因此,如果您没有特别关注对齐,那么您将获得“quazi-optimal”结构,并且编译器可以自由决定什么更适合这组特定的优化选项(是否使用-Os或-O等) 。如果您希望具有特定的对齐方式,则应使用特定于编译器的选项来调整内容。对于GCC和CLang使用__packed__属性,对于MSVC使用#pragma pack。有关详细信息,请参阅pragma pack(1) nor __attribute__ ((aligned (1))) works