代码1: -
struct emp
{
char a;
double b;
};
int main()
{
struct emp e;
printf("%p %p", (void*)&e.a, (void*)&e.b);
}
我的电脑输出: -
OO28FF00 0028FF08
由于char
和double
的大小分别为'1'和'8',因此0028FF00
和0028FF08
是'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
由于char
和long double
的大小分别为'1'和'12',但0028FF04
不是'12'的倍数。
为什么在这种情况下不应用填充?
答案 0 :(得分:3)
long double
是80 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