初始的问题

先来看一个问题,对于下面这两个结构体,它们的大小是一样的吗?

1
2
3
4
5
6
7
struct x
{
char c;
double d;
int i;
} a;
printf("%d\n", sizeof(a));
1
2
3
4
5
6
7
struct y
{
char c;
int i;
double d;
} b;
printf("%d\n", sizeof(b));

你可能认为它们是一样的,但实际上是不一样的,一个是24,另一个是16

也据说是:结构体的大小并不是简单地将每个结构体成员的大小相加就能得到

如何计算结构体大小

首先我们要了解各种基本类型的大小

Type sizeof(Type)
char 1
short 2
float 4
int 4
long 4
long long 8
double 8
long double 16

一般情况

  1. 后声明的类型永远认为结构体是按照自己的类型来的(找当前类型大小的最小倍数位置存放)

  2. 整个结构体补全到最大类型的整数倍

在第一个例子中

先声明了char类型,占用了1字节
然后声明int类型,他发现前4个字节有部分被占用了(无法使用),就跳过4个字节声明了自己,占用4字节
然后声明double类型,前8个字节有被占用,跳过8个字节声明自己,占用8字节

总计16字节,是8的倍数,所以结果为16

在第二个例子中

先声明char占用1字节
然后声明double,前8字节被占用,跳过前8字节声明自己,占用8字节
最后int占4字节

总计20字节,不是8的倍数,补到24

设置了对齐数的情况

  1. 每次都找min(对齐数,类型大小)的最小倍数位置存放

  2. 整个结构体补全到min(对齐数,最大类型大小)的整数倍

很多文章中有默认对齐数这种说法,就是说对齐数默认是设置了的,并认为在Windows中为8,在Linux中为4

但在我用的 MinGW-W64-builds-4.3.5 中貌似没有这个东西,因为我的测试结果与Linux gcc没有默认对齐数(内赋gcc官方大佬邮件)中的相同

如何设置对齐数

要设置编译器的对齐数,我们需要借助于以下预处理命令:

1
#pragma pack()

如果在该预处理命令的括号内填上数字,那么对齐数将会被设置为对应数字

如果不在括号内填写数字,那么会恢复为未设置对齐数状态

对齐数只能为2的次幂

嵌套结构体

如果 A 嵌在 B 中,那么计算 B 的大小相当于计算把引入 A 的那一行替换成 A 中的内容的新结构体的大小

最省空间策略(重要)

先声明类型空间大的,再声明类型空间小的

(数组看作是连续的多个声明)

当然,还可以使用位域,但这东西真的把我给看懵圈了😂