目录
前言:
一、结构体类型的声明:
1.结构的基础知识:
2.结构的声明:
3.结构成员允许的类型:
4.结构体变量的定义:
5.结构体变量的初始化:
二、结构体成员的访问:
1.结构体变量访问成员:
2.结构体指针访问指向变量的成员:
三、结构体传参:
四、总结:
前言:
上周因为考试复习和放假等等原因导致你们勤奋的銮同学停更了近一周,为了弥补上周的停更,这两天我也开启了狂暴日更模式,辛苦各位路过的小伙伴们给我点点关注点点赞,让我有继续狂暴下去的动力,鄙人在此谢过各位大佬了!
上文中我们学习了初阶指针的相关知识,已经对指针有了一定程度的了解和理解,对于指针的应用也是有了一定的心得,关于更深层次的内容我将会在初阶C语言全部介绍完毕后,开启进阶模块为各位小伙伴们进行讲解。而本文我将带领小伙伴们了解下一章节关于结构体的内容。
一、结构体类型的声明:
1.结构的基础知识:
我们常常将结构称为结构体,结构是一系列值的集合,这些值我们称之为成员变量。结构的每个成员可以是不同类型的变量。这里我们应当进行区分:
数组:一组相同类型的集合
结构:一系列允许类型不同的成员的集合
结构体存在的意义是,在我们的日常生活中存在着许许多多的复杂对象,而这些复杂对象具有许许多多的属性,难以通过某种单一类型的值进行描述,例如:
“学生”的属性:姓名、年龄、性别、成绩等等
“著作”的属性:书名、书号、作者、定价等等
于是我们就通过使用结构体这样包含一系列可以为不同类型的值的集合来描述我们想要描述的复杂对象。
2.结构的声明:
与函数使用相同,结构在使用前也需要声明,它的声明格式为:
struct tag
//tag为程序员可以根据需求自定义的标签名
{
member_list;
//成员列表,含有一到多个
}variable_list;
//variable_list为变量列表,用于在声明结构类型的同时定义变量(可以没有)
例如我们在描述“学生”这个复杂变量时可以这样去声明:
struct student
//student为我们根据描述对象“学生”自定义的标签名
{
//结构成员可以是不同类型的变量:
char name[20];
//成员:姓名
int age;
//成员:年龄
char sex[5];
//成员:性别
float score;
//成员:成绩
};
3.结构成员允许的类型:
结构的成员可以是标量(有大小无方向)、数组、指针,甚至是其它结构体(结构体支持嵌套)。
4.结构体变量的定义:
结构体的定义有两种方式,一种是在声明类型的同时定义结构体变量,另一种是在主函数内定义结构体变量:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct student
{
char name[20];
int age;
char sex[5];
float score;
}s1,s2;
//定义结构体变量s1、s2
//此处定义的结构体变量是全局的
struct student s3, s4;
//定义结构体变量s3、s4
//此处定义的结构体变量等同于声明时定义,也是全局的
int main()
{
struct student s5, s6;
//定义结构体变量s5、s6
//此处定义的结构体变量是局部的
return 0;
}
两种定义方式均可,但也有所不同。在声明结构体类型时所定义的结构体变量是全局的,而在主函数内定义结构体变量则是局部的。
5.结构体变量的初始化:
结构体变量在进行初始化时同样有两种方式,一种是在声明时定义并进行初始化,另一种是在主函数内定义并进行初始化:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct student
{
char name[20];
int age;
char sex[5];
float score;
}s1 = { "Zhang",21,"Man",98.4 };
//初始化结构体变量s1,此处的结构体变量是全局的
struct student s2 = { "Wang",20,"Woman",99.5 };
//初始化结构体变量s2,此处初始化的结构体变量等同于声明时初始化,也是全局的
int main()
{
struct student s3 = { "Jiao",21,"Man",67.2 };
//初始化结构体变量s3,此处的结构体变量是局部的
printf("%s %d %s %.1lf\n", s1.name, s1.age, s1.sex, s1.score);
printf("%s %d %s %.1lf\n", s2.name, s2.age, s2.sex, s2.score);
printf("%s %d %s %.1lf\n", s3.name, s3.age, s3.sex, s3.score);
return 0;
}
并且同样的,在声明结构体类型时所定义并初始化的结构体变量是全局的,而在主函数内定义并初始化结构体变量则是局部的:
值得一提的是,结构体在进行初始化时允许进行嵌套初始化:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct student
{
char name[20];
int age;
char sex[5];
float score;
};
struct id
{
struct student s1;
//结构体允许嵌套初始化
char id[20];
};
int main()
{
struct id ID1 = { {"Zhang",21,"Man",98.4 },"2028224096" };
printf("%s %d %s %.1lf %s\n", ID1.s1.name, ID1.s1.age, ID1.s1.sex, ID1.s1.score, ID1.id);
return 0;
}
代码运行起来依然可以得到我们想要的结果:
二、结构体成员的访问:
1.结构体变量访问成员:
结构体变量访问成员是指,通过点操作符 ' . ' 对结构体变量成员进行访问。点操作符接受两个操作数,一个是结构体变量名,一个是结构体成员名:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct AGE
{
int age;
};
void Printf(struct AGE str)
{
printf("该同学的年龄为:%d\n", str.age);
}
int main()
{
struct AGE A1 = { 21 };
//定义并初始化结构体变量A1
printf("该同学的年龄为:%d\n", A1.age);
//通过点操作符访问结构体变量A1的结构体成员age
//点操作符接受两个操作数,一个是结构体变量名A1,另一个是结构体成员名age
Printf(A1);
return 0;
}
如此就可以实现结构体变量对成员的访问了:
2.结构体指针访问指向变量的成员:
而有些时候我们得到的不是一个结构体变量,而是指向一个结构体变量的指针,那么在这种情况下,我们又该如何去访问结构体成员呢?答案是,使用结构体指针访问指向变量的成员:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct AGE
{
int age;
};
void Printf(struct AGE* str)
//接收结构体地址
{
printf("该同学的年龄为:%d\n", (*str).age);
//使用结构体指针访问指向对象的成员
printf("该同学的年龄为:%d\n", str->age);
//或使用'->'操作符,也能实现使用结构体指针访问指向对象的成员
}
int main()
{
struct AGE A1 = { 21 };
//定义并初始化结构体变量A1
Printf(&A1);
//给结构体地址传参
return 0;
}
通过使用结构体指针,我们成功的访问了指向变量的成员:
三、结构体传参:
类似于函数,在函数中访问结构体成员时,也存在着传值调用与传址调用的问题。为了研究这个问题,我们直接上代码进行研究:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct TEST
{
int test;
};
//结构体传参
void Printf1(struct TEST test1)
{
printf("打印测试用例Printf1:%d\n", test1.test);
}
//结构体地址传参
void Printf2(struct TEST* test1)
{
printf("打印测试用例Printf2:%d\n", test1->test);
}
int main()
{
struct TEST test1 = {666};
Printf1(test1);
//传值调用:传结构体
Printf2(&test1);
//传址调用:传结构体地址
return 0;
}
那么上面的两种调用方式哪一种更好呢?我们认为应当首选 Printf2 函数。原因是函数在传参时,参数是需要压栈的,即将整个结构体变量的所有成员数据全部拷贝至函数执行时所创建的临时空间。那么假设在传递结构体对象的时候,结构体过大,参数压栈的系统开销有可能会很大,这种情况下将会导致我们计算机系统的性能的下降:
结论:我们在进行结构体传参时,应当传递结构体的地址。
四、总结:
那么到这里,今天我们关于初阶结构体的学习就结束啦。关于结构体的知识其实还有很多,而我们今天学习的目标仅仅只是让各位小伙伴们能够学会使用结构体,关于结构体更深层次的知识点,我们将在后续的进阶模块全部为各位小伙伴们做更加详细的全面介绍。
通过今天的学习,想必各位小伙伴们已经学会了结构体的使用,大家如果仍然存有疑问,或者对于结构体的使用有自己的一些想法,可以在课下多多尝试,用实验来进行求证。如果实在无法解决,也欢迎各位先伙伴们私信我,我会竭尽我个人所能,为各位小伙伴们答疑解惑。懒惰不会让你一下子跌倒,但会在不知不觉中减少你的收获;勤奋也不会让你一夜成功,但会在不知不觉中积累你的成果!
新人初来乍到,辛苦各位小伙伴们动动小手,三连走一走 ~ ~ ~ 最后,本文仍有许多不足之处,欢迎各位看官老爷随时私信批评指正!