📜  C中的结构体填充(1)

📅  最后修改于: 2023-12-03 15:00:11.972000             🧑  作者: Mango

C中的结构体填充

在C语言中,结构体是一种自定义的数据类型,用于将不同的数据项组合在一起。结构体允许程序员在单个变量中存储多个数据项,并能够以一次操作的形式访问相应的数据项。

在C语言中,结构体填充是指在结构体中插入额外的字节以对齐数据成员。这个过程是由编译器自动完成的,被称为“自动对齐”。

结构体对齐规则

结构体对齐遵循下面的规则:

  1. 结构体中的第一个元素的偏移量为0。
  2. 结构体中每个元素的偏移量必须是它的大小或者对齐粒度的整数倍,其中对齐粒度是编译器自动决定的。
  3. 结构体的总大小必须是最大元素的大小或对齐粒度的整数倍,也就是说结构体的大小必须是对齐粒度的整数倍。

一个例子,我们定义如下结构体:

struct s {
    char c;   // 1字节
    int i;    // 4字节
    char d;   // 1字节
};

对于这个结构体,我们可以使用下面的命令来查看结构体的大小和对齐情况:

$ gcc -DMY_PRINT_SIZEOF -o test test.c  # 生成一个包含大小信息的可执行文件
$ ./test                                # 运行可执行文件查看大小信息

运行结果为:

size of struct s is 12

也就是说,这个结构体的大小是12字节。这里的细节是第二个元素需要按四字节对齐,所以在第一个元素后面需要填充三个未使用的字节来对齐第二个元素,结构体的最后一个元素需要填充两个未使用的字节来对齐结构体本身。

防止结构体填充

对于一些对于性能要求较高的程序而言,结构体填充可能会带来一定的性能损失。因此,有一些方法可以阻止编译器做结构体填充。

一种方法是使用__attribute__((packed))来告诉编译器不要按对齐方式对结构体进行填充,这样可以减少结构体的大小,但可能会影响程序的运行效率。

struct s{
    char c;
    int i;
    char d;
}__attribute__((packed));

还有另一种方法,可以使用#pragma指令来告诉编译器使用指定的对齐方式:

#pragma pack(1)
struct s{
    char c;
    int i;
    char d;
};

这里的pack(1)表示使用一字节对齐,这样可以尽可能地减少结构体的大小,但这对于CPU处理效率不高,因为需要读取不对齐的数据,可能会有性能影响。

总结

在C语言中,结构体填充是编译器自动按照对齐方式对内部数据进行填充的过程。虽然结构体填充可以确保数据对齐,但会带来一定的性能损失,因此程序员可以使用__attribute__((packed))#pragma来避免结构体填充,从而提高程序的运行效率。