目录
前言
本章我们将细致讲解一下结构体这一概念,我们将从结构体基础、结构的自引用、结构体内存对齐、结构体实现位段这几个方面来进行讲解
一、结构体基础
声明举例:
struct stu
{
char name[20];
int age;
char sex[10];
};
结构体中的成员可以是不同类型的变量,而且结构体类型定义完后面一定要记得加一个分号
结构体变量的创建和初始化:
二、结构的自引用
我们可以在结构中包含一个类型为该结构本身的成员
那我们是否可以这样写呢?
struct Node { int data; struct Node next; };
其实是不行的,因为这样的话会导致结构体类型无限的大(类似于永远传递却没有回归)
正确自引用的方式:
struct Node { int data; struct Node* next; };
我们用地址就可以解决上述问题,因为地址的大小不是4个字节就是8个字节,大小不会无限增大
我们还可以在自引用的过程中对结构体用typedef来重命名:
typedef struct Node
{
int data;
struct Node* next;
}Node;
struct Node { int data; struct Node* next; };
typedef struct Node Node
上述这两种方法效果相同
三、结构体内存对齐
我们要掌握结构体的对齐规则从而能计算出给定结构体的大小
对齐规则:
1、结构体的第一个成员要对齐到与结构体所在内存空间起始位置偏移量为0的地址处
2、其他成员要对齐到偏移量为对齐数的整数倍的地址处
对齐数是指编译器默认对齐数与成员变量大小两者之间的较小值(VS里默认对齐数为8个字 节,Linux中没有默认对齐数)
3、结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的) 的整数倍
4、如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结 构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍
我们拿图中的例子详细解释一下怎么计算大小
首先我们要明白偏移量是指与所开辟空间起始地址相隔的距离,我们按照第一条规则把变量c1安排到偏移量为0的空间,共占用一个字节的空间;
接下来安排c2,首先找出c2的对齐数,c2大小为1,默认对齐数为8,二者之间最小值为1,故对齐数为1;我们找到偏移量为对齐数(即1)的倍数的空间,可知紧接下来的空间就符合要求,我们再把c2放进去;
剩下一个i,我们找到 i 的对齐数为4,即找偏移量为4的倍数的空间来存放 i ,
我们再找这三个成员之间的最大对齐数,为4,可知结构体总大小为4的倍数,而此时计算出来的8正好是4的倍数,故算出来大小为8个字节
如何修改默认对齐数:
我们可以用#pragma这个指令来修改编译器的默认对齐数
括号里什么都不加代表恢复默认对齐数
结构体在对齐方式不合适的时候,我们可以自己更改默认对齐数
结构体传参:结构体传参的时候,要传结构体的地址
四、结构体实现位段
什么是位段呢?
如上,位段与结构体相比,就是每个成员名的后面加上一个冒号和数字,其代表的意思是每个成员对应分配的二进制位的个数,比如_a虽然是int类型,但只给分配了2个二进制位
位段的空间是按照成员类型一点一点给的,如果是int,每次给4个字节,不够再给;如果是char,每次给1个字节,不够再给
注意:位段是不跨平台的,注重可移植的程序应该避免使用位段 ,而且位段中的元素类型要保持一致
那怎么计算位段大小呢?
在VS里面,位段是从右往左放的,并且当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,在VS里面剩余的位就被舍弃,重新申请开辟一个空间来存放第二个位段成员
总结: 跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在
本章到这里就结束啦,希望各位小伙伴可以点个关注,支持一下阿鹿,大家的鼓励是我前进的第一动力,3Q~