在计算结构体的大小的时候,我们需要考虑内存对齐问题,这也是比较热门的考点之一
结构体内存对齐的规则(本篇文章全部以VS编译器来做示例)
我们在编译器中可以使用#pragma pack(8)来自行设定默认对齐数,#pragma pack()还可以用这段代码来取消自行设定默认对齐数
1.结构体的大小计算
1.1普通结构体的大小计算
这里我们可以用一段代码来做示例
struct S1
{
char c1;
int i;
char c2;
};
这是C语言中定义的一个结构体,那他的大小怎么来计算呢?
首先我们用一个图来解释
首先我们遵从第一条,让第一个放在偏移量为0的位置
然后c1占用一个字节,所以i要从偏移量为1的位置开始找
然后根据第二条,取最小偏移量,默认的偏移量为8,而int的偏移量为4,所以int应该放到偏移量为4的位置,然后int占用4个字节,依次给他4个空间
最后看c2,取最小偏移量,默认值为8,而char的偏移量为1,所以char应该放到偏移量为8的位置,然后char占用1个字节,依次开1个空间
然后看0-8一共占用了9个字节,在根据第三条规则这个结构体中的最大偏移量是int的4,所以结构体的大小应该为4的倍数,应该是12,所以这个结构体所占用的字节数是12个字节
但是如果我们对代码进行改进,变成这样
struct S2
{
char c1;
char c2;
int i;
};
根据上面的方法可以得到,结构体的大小变成了8,也就节省了4个字节的空间,所以我们定义结构体的时候,最好把占用空间较小的变量放到前面,这样可以提高内存的利用率
1.2嵌套结构体的大小计算
看一段代码
struct S3
{
double d;
char c;
int i;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
printf("%d\n", sizeof(struct S4));
这里我们可以看到,S4进行了结构体的嵌套使用,那么这种情况下应该怎么计算呢?
首先我们用前面的方法可以计算出S3的最大对齐数位8,占用的空间16个字节
然后嵌套之后,看上面的第四条规则:
![](https://img-blog.csdnimg.cn/c7658c137b3c4202b3e1c1ea9d841e33.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55SY5p6z,size_20,color_FFFFFF,t_70,g_se,x_16)
这里我们套用上面的几条规则之后,得出的结果应该是32个字节,如果你不相信我就去测试一下
可以看到,我们的结果完全正确
1.3为什么会存在内存对齐
2.位段
位段的基本要求
struct A {
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
位段的基本大小是以比特位单位的