🤡博客主页:醉竺
🥰本文专栏:《C语言深度解剖》
😻欢迎关注:感谢大家的点赞评论+关注,祝您学有所成!
✨✨💜💛想要学习更多C语言深度解剖点击专栏链接查看💛💜✨✨
目录
1. 结构体内存大小计算(引例)
2. 结构体内存对齐规则
2.1:对齐规则1
2.2:对齐规则2
2.3:对齐规则3
2.4:对齐规则4
3. 实战
上一篇文章中我们学习了结构体的进阶,其中介绍了结构体内存对齐的规则,由于结构体内存对齐需要讲解的篇幅较长,所以这里专门写了一篇文章来讲解。感兴趣的可以先阅读这一篇文章:
《结构体进阶学习》https://blog.csdn.net/weixin_43382136/article/details/138768281
1. 结构体内存大小计算(引例)
下面实例中结构体的类型你觉得是多大? (Visual Stdio环境下)
#include <stdio.h>
struct Stu
{char name;int age;
};int main()
{printf("%d", sizeof(struct Stu));return 0;
}
初学结构体的人会认为,结构体类型的大小是其中各变量的大小之和,上述代码中结构体是 5 字节,其实并非如此!下面是运行结果: 8 (字节)
为什么输入结果是8而不是5呢?这与结构体在内存中特殊的存储方式有关,接下来就引出我们本章的主题 《结构体内存对齐》
2. 结构体内存对齐规则
1. 第一个成员存储在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
- VS中默认的值为8
- GCC环境下没有默认对齐数,此时结构体成员自身的大小就是对齐数
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
上述规则猛的一看会有点懵,什么跟什么啊?请继续往下阅读。
2.1:对齐规则1
- 第一个结构体成员在与结构体变量偏移量为0的地址处。
偏移量:结构体变量中第一个成员的地址 相对于首地址的距离。
对齐规则1中偏移量为0,就代表着结构体变量中第一个成员,是从开辟的整个结构体变量空间的首地址开始存储。
这里我们用以下结构体作为一个例子:下面结构体变量的大小为12字节
struct S1
{char c1;int i1;int i2;
};
我们一步步画图来分析 :
c1 存储位置
2.2:对齐规则2
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8
GCC环境下没有默认对齐数,此时结构体成员自身的大小就是对齐数
1. 当前是VS环境下,默认对齐数是8,后面两个成员分别是 int i1, int i2,它们都是4字节,因此在VS环境下,这两个成员变量的对齐数 就是 “4”。
2. 根据规则2,其他成员变量要对齐到 "对齐数"的整数倍地址处,已知后面两个成员 i1 和 i2 对齐数是 4 ,这个规则意味着,i1 和 i2 要从偏移量为 4 的整数倍位置开始存储。具体看下图:
同理 i2 也是从 偏移量为 4 的整数倍位置开始存储,这里由图可知,需要从偏移量为 8 的位置开始存储,如下图所示:
而偏移量为“1,2,3”的空白处则会
2.3:对齐规则3
- 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
struct S1
{char c1;int i1;int i2;
};
对于上述的结构体例子,应用到规则3,其实就已经结束了,因为规则4是针对嵌套结构体的。
规则3含义:
- 当结构体中的最后一个成员被正确存放后,结构体的总大小并非简单地等于从第一个成员(偏移量为0的位置)到最后一个成员最后一个字节的长度。
- 而是首先判断出所有成员中对齐数中的最大对齐数,c1对齐数是 1,i1 和 i2 对齐数都是 4,因此整个结构体成员中的最大对齐数是 4.
- 最后,如果 从第一个成员(偏移量为0的位置)到最后一个成员最后一个字节的长度不是 最大对齐数 4 的整数倍,则整个结构体占据的总内存需要从最后一个字节继续延伸,直到整个结构体大小是 4 的整数倍。
上个例子中,最后一个成员 i2 成员存储好之后,最后一个字节的位置已经在 偏移量为 11 的位置处了,此时整个结构体变量的总大小已经是 12 了,12是 最大对齐数 4 的整数倍了,所以无需延伸,上述结构体S1类型的总大小就是12字节。
2.4:对齐规则4
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
对齐规则4 其实跟 对齐规则3类似,只不过一个判断成员变量的对齐数,一个是 整个结构体的最大对齐数。
这里我们看一个新的例子:
S2结构体大小为 20 字节
struct S1
{char c;int i1;int i2;
};struct S2
{char a;struct S1 s1; //嵌套结构体char b;
};
3. 实战
接下来会再整一个综合的例子,不再做出详细解释,看图分析即可。
S1的内存分布:
a的对齐数是4,b的对齐数是1,d的对齐数是8,因此 S1整个结构体的最大对齐数是8,总体大小为16字节。
S2的内存分布:
ch 的对齐数是1,s1 的对齐数是8, i 的对齐数是4,因此S2结构体类型最大对齐数是8.