C 与数据结构关联的混淆?

C 与数据结构关联的混淆?,c,struct,padding,long-double,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 由于char和double的大小分别为'1'和'8',因此0028FF00和0028FF08分别是'1'和'8'的倍数 代码2:- struct emp {

代码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'的倍数


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

就我所知,填充和数据对齐在很大程度上取决于目标体系结构、编译器优化选项和optimizator的总体质量。因此,如果您不特别关心对齐,那么您会得到一个“quazi optimal”结构,编译器可以自由决定对于这组特定的优化选项(使用-Os还是-O,等等)什么更好。如果您希望有一个特定的对齐方式,那么应该使用编译器特定的选项来调优这些内容。对于GCC和CLang use属性,对于MSVC使用。有关更多信息,请参见一个
长双精度
是一个字节,因此需要10个字节。10确实不是一个很好的大小,因此Intel 32位处理器决定使用12字节。12是4的倍数,表示32位(3 x 32位)。这被认为是对齐的,因为32位处理器只需要4字节对齐,所以12字节在任何4字节边界对齐。显然,编译器知道它在做什么,并且总是试图生成尽可能最小的结构

这就是说,在这里您可以看到,您不能使用结构声明,而希望将其保存为文件中的原样。。。至少不能使用默认的C类型(您可以使用int32_t、uint64_t等来获得您想要的内容,但对于浮点数没有等效项…)


正如有人评论的那样,在64位体系结构上,longdouble是16字节。浪费了6个字节。。。但它使类型始终保持64位对齐。

维基百科有一个典型对齐表:

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


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

首先使用
%p
而不是
%u
,并将地址转换为
void*
@GrijeshChauhan:我知道,但我的问题是关于填充的。问题是关于填充的,确实是个好问题,但在C中,使用正确的格式类型是未定义的行为。因此,我建议您使用
%p
再试一次,并将地址转换为
void*
并更新问题。@GrijeshChauhan:我这样做了,但问题仍然是一样的。对齐与本机架构的大小有关,而不是与结构大小有关。512字节大小的结构也将根据系统而不是512字节对齐到4/8/16字节,这不是Intel决定的。x86上只有32位加载/存储与4字节对齐,而不是所有其他数据类型。这只是一个建议,而不是要求,因为它们仍然可以使用未对齐的数据进行操作,尽管会降低性能。在现代x86处理器上,即使是32位模式也需要双精度8字节对齐,SSE数据必须对齐16字节,AVX为32字节(新的AVX-512可能为64字节)。是的。。。处理器可能被设置为接受任何对齐,或者在使用“错误”指令加载未对齐的数据时崩溃。这比我在这里解释的要复杂一点,但是OP只询问长双精度和C结构对齐。要了解更多细节,我建议阅读《英特尔64/IA32体系结构软件开发人员手册》。