从零到一助你掌握结构体

我是struggle,编程小白一枚,今天让我们来一起学习关于结构体的知识吧!😃😃

图片1-1

在我们编写程序的时候,尤其是在编写类似图书馆管理系统,学生信息管理系统这样的课设项目时,会用到很多变量,定义起来太过麻烦,那有没有能让我们一次定义多个变量的方法呢?这就是我们今天要学习的,有关于结构体的知识。

🚩1.结构体基本知识以及定义结构体:

c语言的类型分为两大类:一类是内置类型,例如:int 、double 、char…
一类是自定义类型,也就是:结构体、枚举、联合体。今天我们着重介绍一下结构体。
刚才我们提到,结构体是一种自定义的类型,这个自定义体现在哪里呢?而结构体又是什么意思呢?我们先来看一段代码:
在这里插入图片描述
这里面的struct是结构体的关键字,就是告诉计算机,你要定义一个结构体了 Student就是结构体的名字,可以任意选取,中括号里的就是你需要这个结构体包含哪些成员。我这里定义的结构体是一个学生,需要的成员有学生年龄,学生姓名,以及学生的成绩,那我就在中括号中定义三个变量(也就是成员),对应我的需求。这些成员可以是普通的数据类型,指针,可以是数组,甚至还可以是结构体,最后别忘了,中括号最后要加 ; 要不然会报错的。
事实上,结构体也就是个类型,只不过是一个我们自己定义的类型,这个类型中可以包含很多个其他的类型,我们也可以说,结构体是一个复合型类型,是很多类型的集合。

1.1定义结构体的情形

在讲述定义结构体类型情形之前,我们先简单的了解一下如何定义一个结构体变量:
结构体变量可以通过struct +结构体名字+变量名来定义

struct student s1;

1.标准形式
最普遍的方式就是我们在上文中提到的:
在这里插入图片描述
在定义了这样一个结构体之后,我们就可以通过struct + 类型名+变量名来定义一个结构体变量了。
2.
第二种方式则是在定义结构体类型的同时,定义一些对应的结构体变量,数量由我们自己决定:

在这里插入图片描述
这里的s1,s2与我们正常定义的结构体变量大体上是相同的,如果非要找一点区别,那就是我们定义在主函数里的结构体变量是局部变量,而这里定义的是全局变量。

3.也可以不要结构体类型的名字,直接定义一个类型:
在这里插入图片描述

我们可以看到,这种方式定义结构体的时候没有任何的问题,但是在定义一个新的结构体变量时,编译器报错了,这是为什么呢?我们刚才说过,定义一个结构体变量要用struct+结构体名+变量名来定义,现在我们没有结构体的名字,自然也就无法定义一个新的结构体变量,但是要注意,由于我们在定义这个结构体时就给了他两个结构体变量s1,s2,所以我们只能使用这两个变量,就像是一次性消耗品,用了就没有了。

1.2结构体嵌套以及常见错误

之前我们说结构体的成员可以是结构体,那具体怎么实现呢:
在这里插入图片描述
可以看到,我们在结构体内部又定义了一个结构体,并且没有报错,这是被允许的,看到了这里大家可能有一个疑问,既然可以这样嵌套,那我可不可以在定义结构体的过程中定义一个此结构体的结构体变量呢?
在这里插入图片描述

当然,这是万万不能的,可以看到,编译器给了一个未定义的错误,事实上,他的错误点应该是这样的在结构体中定义此结构体的变量,相当于你的第一次定义结构体没有定义完,你就再次定义变量,这时你默认结构体已经声明完了,事实上,结构体还在声明的过程中,无法给出结构体变量的完整信息,所以我们要尽量避免这种错误

1.3小结

在这里呢,比较推荐第一种定义方法,很规范,也不容易出错,第三种定义方法很少有,只有在嵌套的时候才会用上一些。

🚩2.结构体变量

2.1结构体变量的定义

当我们声明了一个结构体类型之后,就可以用这个类型来定义变量了,用结构体类型定义的变量就叫做结构体变量,而定义的方式呢,也和我们之前学习的定义方式相差不多:

struct student s1;

struct+类型名+变量名
有时候我们会觉得每回都加上struct很麻烦,不符合我们之前类型名+变量名的定义方法,但是不加就会报错,很难受,但其实也有办法来解决这件事:
在这里插入图片描述
如果这样操作,那我们在定义的结构体变量的时候就可以采用类型名+变量名的方式来定义了,这里来简单的说一下他的原理是什么:
typedef也是一个关键字,用于给复杂的结构取一个简单的别名
在msdn上我们来查一下他的定义以及用法:
在这里插入图片描述
可以看到typedef的用法是:
typedef+要改名字的类型+新的名字;
在我们上面的用法中就是 struct Student{}是要改名字的类型,新名字还是Student,所以我们就可以直接用Student+变量名来定义一个新的结构体变量了

2.2结构体变量的初始化以及调用

如果你定义了一个结构体变量,而没有对他初始化,那他成员的值就自然是一个随机值:
在这里插入图片描述

当我们看到这里的时候,发现一个结构体变量下面还有三个成员变量,这样的结构我们还没有遇见过,那他在内存中到底是怎么储存的?我们来研究一下:

♨️♨️ 2.2.1结构体变量的存储

正常变量在内存的存储我们已经很清楚了,先申请一片空间,再把变量值存进去,然后这个变量还会有一个地址:
在这里插入图片描述
那当我们定义了一个有三个成员的结构体变量s1,他的存储应该是怎么样的呢?我们画图理解一下
在这里插入图片描述

可以看到,整个结构体变量的空间分成三份,4个字节给age 4个字节给grade,20个字节给了name,也就是说结构体变量在申请空间的时候,把三个成员的空间一起申请了,然后分配,事实上,结构体变量的大小是有规则的,叫做字节对齐,这个规则我们不细讲,可以简单说一说,例如:

struct a
{
int a;
double b;
char c;
};

你觉得这个结构体变量的大小应该是多少?4+8+1?让我们使用sizeof看一看
在这里插入图片描述
他的大小居然是24个字节,这是因为double的字节是8个,在进行申请时,他的空间最大,其他成员申请的时候,都要自动提升到8个,所以这时候,他的空间就是3*8=24。不必深究,实际上一共有四条规则,能理解最好,不理解在以后的文章中会有更详细的讲解。
现在我们要知道的就是,结构体变量在申请的时候会申请一大片空间就好了

现在继续讲初始化,在我们对结构体变量的进行操作的时候,会用到一个访问符: . (作用域访问符)通过这个访问符,就可以访问到成员变量了:
在这里插入图片描述
这就是我们的第一种初始化方式,通过访问符一个一个进行赋值初始化,当然这算不得真正的初始化,初始化应该在定义的同时进行初始化才行:
在这里插入图片描述
按照成员变量的顺序,通过逗号分隔开,这就是最正常的初始化方式了,也是最常用的初始化方式。剩下还有一些初始化方式,但事实上用的情况很少,就不一一赘述了。

🚩3.结构体指针

这一部分,我们简单的了解一下结构体指针的含义以及用法:
结构体指针,顾名思义,指向结构体的指针,而且要注意指针的两型,还不明白的话可以看看我的上一篇博客哦,万字详解C语言指针,所以我们就要用一个结构体类型的指针指向一个结构体,具体操作如下:
在这里插入图片描述
指针的两型也完全对应上了,但是结构体里面那么多变量,我们该如何引用呢,按照我们之前的方式,都是用号来解引用,那我们先来试试,可不可以:
在这里插入图片描述
看到,按照我们之前学习的思路
p就等于结构体变量s1,通过s1.就可以访问到成员变量,可是这样未免太麻烦了,有没有简单一点的方式呢?
在这里插入图片描述
事实上,有的,通过箭头->,形象表达出指针指向结构体成员变量,这和我们之前进行的(*p).name =10是等价的,通过指向的形式进行操作,更加的方便好记。

3.1结构体传参

既然结构体是个自定义类型,那结构体自然也可以当作参数,也有址传递与值传递这两种:
在这里插入图片描述
可以看到,两种传递方式都是可以的,但是哪一种更好呢,第二种更好些,因为我们知道,如果进行值传递,那形参是实参的拷贝,要额外复制一份,而结构体变量中,变量可能十分复制繁多,这时候复制就会给栈的空间带来极大的占用,所以我们优先使用址传递的方式来进行操作。

🚩结语

当你学习到这里,今天的内容就到此结束了,当然,我们只是简单的了解了一下结构体的作用,更深入的内容我们放到以后来说,比如结构体申请空间的规则到底是怎么样的?其他几种自定义类型又有什么样的作用?大家感兴趣的话欢迎评论催更,struggle会加急为大家带来下一篇内容😆如果你觉得我的文章对你有帮助,不妨点个关注期待一下下一期的内容呀😆😆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值