一、结构体是什么
在C语言中,我们常常需要将多种不同类型的元素包装起来,结构体正是满足我们这一需要的一种自定义变量类型,通过结构体,我们可以仅仅使用结构体访问操作符,就能代替曾经十分繁琐且容易搞乱的多个变量使用。
二、结构体变量的创建和声明
结构体创建和声明的关键字是struct
其基本格式可以归纳为下列代码:
struct tag
{
member-list;
}variable-list;
1.其中tag为结构体的标签,创建出来的结构体变量类型可以用struct tag来表示(类似于整数变量int a,结构体变量的创建是struct tag a),一般情况tag不可省略
2.member-list为结构体的成员列表,也是结构体变量最核心的部分,在此处可以添加数组,整数,字符类型等等一系列希望包装的类型,如:
struct a
{
char a1[30];
int a2;
char a3;
};
3.variable-list用于快捷创建变量以及对应的指针变量,数量可以是0(也就是说这一部分是可以直接省略的),也可以是多个。
例如:
struct a
{
char a1[30];
int a2;
char a3;
}*pa,ba,la;
此处正是创建了struct a*类型的结构体指针变量pa,两个struct a类型的结构体变量ba,la。
三、结构体变量的初始化
结构体变量的初始化可以按照默认顺序也可以不按照,当然就简洁度而言还是默认顺序好点,在此分开描述:
例如描述一个学生的结构体变量,声明如下(创建了一个学生的结构体变量,包括学生的姓名,性别,年龄,学号):
struct Stu
{
char name[30];
char sex[8];
int age;
char id[10];
}s1,s2;
(一)默认顺序初始化
即先用大括号括起来,再分别对每一个变量进行常规初始化,中间用逗号隔开
struct Stu s1 = { "zhangsan","nan",19,"20220102" };
(二)非默认顺序初始化
使用大括号括起来,使用结构体成员访问操作符.来对希望优先初始化的成员变量进行赋值
struct Stu s2 = { .age = 20,.sex = "nv",.name = "liesi",.id = "20220204" };
四、结构体的内存对齐
(一)、
结构体的内存对齐就是结构体在内存中的存储规则,先来普及一下两个概念:
1.起始位置:就是内存中默认的结构体所占用的起始地址
2.偏移量:自起始位置开始0,1,2,3.......的编号,每个编号相隔大小为一个字节
(二)、
结构体的内存对齐遵循以下规则:
1.第一个成员存放到起始位置(偏移量为0)的地址处
2.其他成员变量都存在对齐到某个数字(对齐数)整数倍的地址
其中,对齐数=默认对齐数与自身成员变量大小中的较小值
3.结构体的总大小为最大对齐数的整数倍(达不到自动占用空间)
4.若嵌套了结构体,嵌套的结构体变量对齐到自身成员中最大对齐数的整数倍处,整体大小依旧为最大对齐数的整数倍。
下面用一个例子辅助理解:
struct n1
{
char c1;
char c2;
int i;
}n1;
struct n2
{
char c1;
int i;
char c2;
}n2;
此时,若是我们sizeof(n1),结果会是8,但是sizeof(n2),结果却是12,
由此可见,存相同的数据组,存的顺序不一样,对应的空间大小也会不同
对于n1:
其中,根据规则第二条,对于char类型的c1和c2来说,对齐数都是1,所以直接存入,但是对于整数类型int来说,对齐数为4,因此需要跳过两个字节进行存储,最后总体大小为8,恰好为最大对齐数4的整数倍。
对于n2:
其中,根据规则一,c1类型先存,再根据规则二,int类型需要舍弃3字节空间存储,c2的char类型则因为对齐数为1得以直接存入,最后总体大小为9,但是最大对齐数为4,因此总体大小对齐到了12。