前言
这一期我们将继续讲解结构体的知识,还没有看过上一期的小伙伴一定要赶紧去学习哦。
上一期,冲鸭!
那么话不多说我们开始今天的学习吧!
文章目录
- 1,结构体的自引用
- 2,匿名结构体
- 3,位段
- 4,结构体的传参
- 5,尾声
1,结构体的自引用
什么是结构体的自引用呢?简单来说就是自己装自己(有点类似递归)。
那么是这样自引用的么?
struct student
{
char name[20];
int age;
float score;
struct student next_student;//这是我们自己定义的一个类型的解耦提变量如果可以这样写,我们就可以在一个学生的结构体里包含下一个学生的结构体,如果有一百个学生,我们就可以通过第一个学生访问到第一百个学生
}stu1;
但是这样写好像有问题啊,我们刚学过内存对齐的知识,在编译期间,编译器需要知道结构体变量大小为结构体变量分配空间,可是这个好像没法知道这个结构体变量的大小是多少,会陷入无限的递归之中。那我们是不是可以换个思路呢?我们不是在结构体成员中加入下一个学生的结构体变量,而是加入下一个学生的结构体变量的地址不就可以了么,这样就不会陷入无限的递归之中。而且我们能通过地址寻找到下一个学生的信息。书写方式如下:
struct student
{
char name[20];
int age;
float score;
struct student* next_student;//储存下一个学生(结构体变量)的地址
}stu1;
2,匿名结构体
匿名结构体是什么呢?就拿我们刚才创建了类型为为student的结构体。如果我们这样写代码呢?
struct
{
char name[20];
int age;
float score;
}stu1;
是不是发现少了student,这种特殊的声明我们就称之为匿名结构体。
但是需注意的是匿名结构体的变量只能在声明时创建且只能有一个变量。也就是说只能使用一次,我们不能对匿名结构体自引用。
3,位段
学习位段之前我们先看如下代码。
struct student
{
char name[20];
int age:6;
int score:8;
};
我们发现该结构体的成员中年龄和分数后面多了一个:和一个数字,这是代表什么意思呢?正常情况下,一个学生的年龄应该在6-31岁之间,因为年龄是个整形数据,所以会给它分配4个字节大小的空间,但是如果只要表达0-31这些数字的话完全不需要那么大的空间对于有符号整形来说只需要6个bit位就足够了,那么回到代码,int age:6;的意思就是给这个整形分配6个比特的空间。而score给他分配了8个字节的空间。那么这个时结构体的内存是如何分配的呢?
struct uma
{
int a:2;
int b:3;
int c:5;
int d:10;
以这个结构体为例。
相比通过这张图片就能够了解位段是如何分配空间的了。
但是我们还需注意以下几点。
1, 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以 选择其他类型。
2, 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。
4,结构体的传参
在函数中我们该怎么对结构体进行传参呢?
我们有以下两种方法
#include <stdio.h>
struct Student
{
int data[1000];
int num;
};
struct Student s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct Student s)
{
printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct Student* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //传结构体
print2(&s); //传结构体的地址
return 0;
}
那么这两种写法哪种更好呢?没错就是第二种,因为直接传递结构体的话,计算机会给形参重新开辟一块内存空间,小的还好说,要是特别大的结构体那么会相当的浪费内存,而传递地址就不一样了并不需要重新开辟一片空间,可以提升程序的性能。
5,尾声
学习完这两篇博客的小伙伴想必已经非常了解了结构体的用法,但是也要多加练习哦正所谓熟能生巧,下次我将找几道结构体的题目来跟大家分享一下。
如果觉得博主讲的不错的千万不要忘记关注博主哦,你们的关注我是最大的动力!