在C结构中填充u_long

在C结构中填充u_long,c,struct,padding,C,Struct,Padding,我在C中定义了一个结构,如下所示: struct example { int ex1; u_long ex2; float ex3; float ex4; }; 所以示例的所有成员的大小都是20,但示例的大小是24,这意味着正在添加填充。我真正不明白的是为什么和在哪里 如果我的术语不正确,请原谅,但我认为因为它是4字节干净的(即所有成员的大小%4==0),所以不需要添加填充。是因为我运行的是x86,所以它需要8字节干净,还是这只是正常情况 然后我真的不知道在哪里添加了填充,我假

我在C中定义了一个结构,如下所示:

struct example {
  int ex1;
  u_long ex2;
  float ex3;
  float ex4;
};
所以示例的所有成员的大小都是20,但示例的大小是24,这意味着正在添加填充。我真正不明白的是为什么和在哪里

如果我的术语不正确,请原谅,但我认为因为它是4字节干净的(即所有成员的大小%4==0),所以不需要添加填充。是因为我运行的是x86,所以它需要8字节干净,还是这只是正常情况


然后我真的不知道在哪里添加了填充,我假设在u_长度附近,但我不确定。

结构通常也在末尾填充,因此结构的总大小可以被具有最大对齐的成员的所需对齐均匀分割

在您的例子中,
u_long
需要8个字节的对齐,并将其放在第一个成员末尾后4个字节,以便其地址位于8字节边界上。结构的总大小变为24,因此在结尾不需要任何额外的填充


末端填充可确保在按顺序排列时,第二个元素不会破坏某些成员的对齐。

以下是一个测试,在一台特定机器上运行,结果可能会有所不同:

$ cat ul.c
#include <stdio.h>

struct example {
  int ex1;
  unsigned long ex2;
  float ex3;
  float ex4;
};

struct example ex;

int main ( void ) {
        printf("Size:\t%zd\n", sizeof(ex));
        printf("ex @\t%p\n", &ex);
        printf("ex1 @\t%p\n", &ex.ex1);
        printf("ex2 @\t%p\n", &ex.ex2);
        printf("ex3 @\t%p\n", &ex.ex3);
        printf("ex4 @\t%p\n", &ex.ex4);
        return 0;
}

$ ./ul
Size:   24
ex @    0x600940
ex1 @   0x600940
ex2 @   0x600948
ex3 @   0x600950
ex4 @   0x600954
$cat ul.c
#包括
结构示例{
int ex1;
无符号长ex2;
浮动ex3;
浮动ex4;
};
结构示例ex;
内部主(空){
printf(“大小:\t%zd\n”,大小(ex));
printf(“ex@\t%p\n”和&ex);
printf(“ex1@\t%p\n”和ex1);
printf(“ex2@\t%p\n”和ex2);
printf(“ex3@\t%p\n”和ex3);
printf(“ex4@\t%p\n”和ex4);
返回0;
}
美元/升
尺码:24
ex@0x600940
ex1@0x600940
ex2@0x600948
ex3@0x600950
ex4@0x600954
这里的填充在ex1和ex2之间

我认为由于它是4字节干净的(即所有成员的大小%4==0),所以不需要添加填充

这不是一个安全的假设。C对
struct
表示中可以添加多少填充,或者在何处添加,几乎没有限制。它完全没有说明什么时候或者为什么。这些选择取决于编译器

是因为我运行的是x86,所以它需要8字节干净,还是这只是正常情况

您认为“8字节干净”与填充有关。也许可以,但同样,这是一个实施决策


一般来说,编译器插入填充以确保所有成员都可以对齐,以便在
struct
s数组的每个元素中进行最佳访问。这可能需要在成员之间或末尾填充,或两者都填充。但这仍然是一个实施方面的考虑。如果您想知道您正在使用的特定C实现是如何解决这个问题的,那么您需要查阅它的文档。

您可以使用宏来了解。没有一种类型具有明确定义的大小。您可能会在字段之间获得额外的填充。谢谢@JoachimPileborg!我在这里使用了这个建议,因为我很懒,但我不知道宏存在。或者可能是在u_long之前,所以它是以8字节对齐的boundary@JohnHascall:这个例子当然是这样,我只是没能做数学:-)好吧,我明白了,因此,这是结构构件所需的最高对齐度,决定了结构的对齐度。我签入了gdb(感谢),填充在末尾。非常感谢。“结构通常也在末尾填充”。这是不正确的。在需要进行适当对齐的地方,可以(并且正在)添加填充字节。唯一的例外是在第一个成员之前。@Olaf:关于填充的决定完全取决于实现,而语言规范并没有要求太多,这是对的,但是主流平台上的大多数“传统”实现都按照我所描述的那样做。代码不应设计为采用某种布局,但最好了解编译器执行某些操作的原因。只需补充:标准保证第一个成员位于偏移量0处。