👑个人主页:啊Q闻
🎇收录专栏:《C语言》
🎉道阻且长,行则将至
一.初识结构体
1.结构的声明
结构是一些值的集合,这些值称为成员变量。结构的每个成员都可以是不同的类型,可以为整型,字符型,也可以为指针,数组等。
举个例子:
struct Stu
{
char name[20];//姓名
int age;//年龄
char sex[5];//性别
char id[20];//学号
};//注意该处有个分号
2.结构体变量的创建和初始化
#include<stdio.h>
struct Stu
{
char name[20];
int age;
char sex[5];
char id[20];
};
int main()
{
struct Stu s = { "张三",20,"男","202311588" };//按照结构体成员的顺序初始化
printf("name:%s\n", s.name);
printf("age:%d\n", s.age);
printf("sex:%s\n", s.sex);
printf("id:%s\n", s.id);
printf("\n");
struct Stu ss = { .age = 18,.name = "lisi",.id = "202311544",.sex = "男" };//按照指定顺序初始化
printf("name:%s\n", ss.name);
printf("age:%d\n", ss.age);
printf("sex:%s\n", ss.sex);
printf("id:%s\n", ss.id);
return 0;
}
详解:
3.结构的特殊声明
在声明结构的时候,可以不完全声明,我们称这种为匿名的结构体类型,如果没有对结构体类型重命名的话,基本只能使用一次。
即:
二.结构的自引用
结构如何实现自引用呢?
我们先看一个例子:
struct Node
{
int data;
struct Node next;//该处为结构自引用
};
上述代码其实不正确,因为一个结构体中再包含一个同类型的结构体变量,那这样的结构体大小不就是无穷大吗?是不合理的。
正确的自引用:
struct Node
{
int data;
struct Node*next;//利用指针进行自引用,就可以避免上述情况
};
三.结构体的大小
了解结构自引用后,我们是不是有些好奇结构体大小是如何计算的呢?
这里我们需要了解结构体的内存对齐规则。
1.对齐规则
规则如下:
1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处。
2.其他成员变量要对齐到对齐数的整数倍的地址处。
3.对齐数=编译器默认的一个对齐数与该成员变量大小的较小值。(VS默认的值为8,Linux中gcc没有默认的对齐数,对齐数就是成员自身的大小)。
4.结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的整数倍。
5.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。
我们从下面代码中具体体会:
代码一:
详解1:
代码二:
详解2:
代码三:
详解3:
对齐规则的意义:结构体的内存对齐是拿空间换取时间的方法,在设计结构体的时候,我们既要满足对齐,又要节省空间,所以:让占用空间小的成员尽量集中在一起 。
2.修改对齐数
我们可以利用#pragma这个预处理指令,达到改变编译器默认对齐数的目的
代码如下:
四.结构体传参
结构体传参通常有两种方式:传值和传址
代码如下:
但两者相比,我们首选传址,因为:
函数传参时,需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象时,结构体过大,参数压栈的系统开销比较大,会导致性能下降。
谢谢大家阅读,如果对你有帮助,三连三连支持一下🎈