前言:我们知道c语言有整型,浮点型等数据类型,而这些都是c语言自带的类型。在本章,将简单的介绍自定义类型——结构体。
结构体
1.结构的基础知识
结构体是一些值的集合,这些值称为成员变量。结构体的每个成员都可以是不同类型的值。比如可以是数组,指针,甚至是其它结构体。
因此,可以通过结构体完成对一个对象特征的简单描述。
2.结构体的声明
标准框架如下:要切记在大括号结尾后有一个
;
以描述一个学生为例:
struct Student // tag:标签,想要描述的对象是学生,tag写成student
{
//member-list:成员列表,描述对象的特征
char name[20]; //姓名
int age; //年龄
float weight; //体重 等等,还有其它特征可以继续增加
}s1,s2,s3; //variable-list:变量列表,具体的描述对象,如s1为学生1,s2为学生2,s3为学生3
结构体变量的创建
创建结构体变量之前,要了解到底哪部分才是结构体类型,下面将通过类比的方式为大家解释:
int a; //变量名是a,类型是整型
struct Student s1; //类比上面,类型是struct Student ,变量名是s1
是不是一目了然?
结构体变量的创建有多种形式:
#include<stdio.h>
struct Student
{
char name[20];
int age;
float weight;
}s1, s2;//全局变量
struct Student s3;
struct Student s4;
int main()
{
//局部变量
struct Student s5;
struct Student s6;
return 0;
}
上面的代码共创建了6个结构体变量:
s1,s2是在声明定义类型的同时创建的变量,且是全局变量
s3,s4,s5,s6是在声明定义类型后创建的变量,但s3,s4是全局变量
,而s5,s6是局部变量
3.结构体的初始化(定义变量的同时赋初值)
在创建整型,浮点型等类型时我们会对其初始化,同样的,结构体类型我们也可以对其初始化。
按顺序初始化
严格按照结构体成员的顺序初始化操作:仍旧以一个学生为例且用数组赋初值来类比
我们知道:数组是一组相同类型元素的集合,而结构体是一些不同类型元素的集合,二者略有相似之处。
#include<stdio.h>
struct Stu //创建学生结构体
{
char name[20];
int age;
float weight;
}s1; //结构体变量s1
int main()
{
int arr[5] = {
1,2,3,4,5 };
//数组赋初值用一个大括号,且每个元素用,隔开
struct Stu s1 = {
"zhangsan",20,70.3f};
//与数组类似,赋初值也用一个大括号,每个元素用,隔开
//需要注意的是;赋初值必须严格按照结构体成员的顺序
//如上面的第一个为名字,第二个为年龄,第三个为体重
return 0;
}
不按顺序初始化(定要掌握此方式)
可以按照自己想要的顺序对结构体初始化
首先得认识.
(结构体成员访问操作符)
具体形式为.结构体成员
请看如下代码:
#include<stdio.h>
struct Stu
{
char name[20];
int age;
float weight;
}s1;
int main()
{
struct Stu s1 = {
.weight=70.3f,.age=20,.name="zhangsan"};
//逆序,先给体重赋初值,再给年龄,名字赋初值
return 0;
}
在VS中使用时只要输入个
.
就有了成员选择,非常方便:
4.结构体成员的访问(打印结构体成员)
,打印结构体时需要访问结构体成员,而结构体成员的访问有2种形式:
结构体变量
.
结构体成员
结构体指针->
结构体成员
请看示例代码:
#include<stdio.h>
struct Stu
{
char name[20];
int age;
float weight;
}s1;
int main()
{
struct Stu s1 = {
.weight=70.3f,.age=20,.name="zhangsan"};
struct Stu* s2 = &s1; //将结构体变量s1的地址存入s2中,s2是个结构体指针
printf("%.2f %d %s\n", s1.weight, s1.age, s1.name); //结构体变量.结构体成员
printf("%.2f %d %s\n", s2->weight, s2->age, s2->name);//结构体指针->结构体成员
return 0;
}
打印结果如下:
可以看到上述两者打印的效果是一样的。
可能有读者会有疑问,上面的指针打印不是画蛇添足吗?我直接用第一种方式打印不就行了吗,还传个地址再打印干什么?
答: 上面的结构体指针打印只是作为示范的一个例子,事实上许多地方都要用到结构体指针打印,比如说结构体传参时传结构体地址的情况。
5.结构体传参
结构体传参可以选择传结构体变量,也可以选择传结构体地址。但推荐选择后者。
这是因为:函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销就比较大,会导致系统性能的降低。
比如结构体成员有个是int arr[1000],传结构体的地址的话只需要把首地址传过去就行了,大大减少了压栈开销。
总结:结构体传参时,要传结构体的地址