是什么结构体
在编写程序时,我们遇到的不止有简单的变量、数学运算,当我们想要表达一个复杂的数据类型时,但是不巧的是C语言中自带的类型没有时,我们该怎么办呢?
此时就可以运用到结构体来定义那些复杂的变量类型。结构体这样的语法就提供了“ 自定义类型 ”,所谓结构体就是某些值的集合。我们将一个物体不同的属性,也就是它所包含的不同类型的变量,放到一起,而这个集合我们可以抽象的看成是这个物体。
我们将一个个对象抽象化,提取其中的核心元素,赋予不同的值,然后表示出来,这样就可以形成同一类型的不同个体。
结构体的定义
假如,我们想要描述一个学生,我们可以将学生抽象成为一个结构体,把他的基本信息写进这个结构体重,作为他的成员变量:
struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
};
通过上述代码,我们就定义好的一个名为Student
,有三个成员变量name、id、sex
,那么如何使用呢?如下所示:
struct Student stu1={“张三”,20201111,’f‘};
这样我们就定义好了一个结构体变量,并且初始化(下面会详细讲),不过我们看到这样的结构体变量写起来很长,很冗余,每次定义的时候都要加上struct
关键字,那么有以下方法可以改进:
struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
};
typedef struct Student student;
student stu1={“张三”,20201111,'f'};
我们知道typedef
关键字的作用是将一个数据类型自定义一个新的名称,所以,在上述代码中倒数第二行,我们使用了typedef
这个关键字,所以我们在定义结构体变量的时候,就可以如上述代码最后一行一样,方便简单,省了很多麻烦;不过,我么还可以写成下面的形式:
typedef struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}student;
student stu1={“张三”,20201111,'f'};
这样就不用再多写一行了,比较方便,代码看起来结构也比较清晰。
结构体变量的定义及初始化
定义
-
结构体变量定义的两种方法:
- 1、在声明时定义:
struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}stu1, stu2;
-
这种方法,我们定义了两个结构体变量,
stu1,stu2
,不过在这种情况下,不能使用typedef
,这一点要注意;
2、在使用时定义:
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}student;
//主函数入口
int main()//主函数,函数入口
{
student stu1, stu2;
return 0;
}
-
上面正是我们在使用时才定义的结构体变量,我们定义了两个结构体变量,
stu1,stu2
;
初始化
-
结构体变量初始化的两种方法:
- 1、在声明定义结合在一起时初始化:
struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}stu1={"张三",20201111,’f‘}, stu2={"小红",20202222,'m'};
- 2、在使用时定义的时候初始化:
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}student;
//主函数入口
int main()
{
student stu1={"张三",20201111,'f'};
student stu2={"小红",20202222,'m'};
return 0;
}
注:结构体初始化或者赋值的时候,一定要注意顺序,要和结构体中的属性的顺序一致,否则就会报错。
结构体成员的访问
结构体变量访问成员
在结构体中,当我么创建一个结构体变量的时候,我么就可以使用这个结构体变量来访问它对应的那些属性;
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}student;
int main()//主函数,函数入口
{
Student stu1 = { "张三", 20201111,‘f’ };
Student stu2 = { "小红", 20202222,‘m’ };
printf("stu1的姓名为:%s,学号为:%d,性别为:%c\n", stu1.name, stu1.id,stu1.sex);
printf("stu2的姓名为:%s,学号为:%d,性别为:%c\n", stu2.name, stu2.id,stu2.sex);
return 0;
}
通过上面的例子,我么可以看出,我么使用结构体变量访问成员变量时,使用的是.
操作符,格式为:结构体变量.成员变量名
,这样我么就可以操作到成员变量。
结构体指针访问成员变量
结构体指针实际上就是将结构体变量的地址赋给指针,然后利用指针来操作成员变量;
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct Student
{
char name[1024];//姓名
int id;//学号
char sex;//性别
}student;
//主函数,函数入口
int main()
{
Student stu1 = { "张三", 20201111,‘f’ };
Student stu2 =&stu1;
printf("stu1的姓名为:%s,学号为:%d,性别为:%c\n", stu2->name, stu2->id,stu2->sex);
return 0;
}
结构体嵌套
在结构体的使用中,我们可以在一个结构体中,将它的成员变量写成另一个结构体,这就叫做结构体嵌套:
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char name[50];//姓名
int id;//学号
}Student;
typedef struct area
{
Student students[10];
}Area;
typedef struct city
{
Area areas[10];
}City;
typedef struct province
{
City cities[10];
}Province;
typedef struct country
{
Province provinces[10];
}Country;
//主函数,函数入口
int main()
{
Country country;
Country* pCountry = &country;
country.provinces[0].cities[0].areas[0].students[0].id = 111;
strcpy(pCountry->provinces[0].cities[0].areas[0].students[0].name, "Misaki");
printf("学生的学号为:%d,姓名为:%s\n", country.provinces[0].cities[0].areas[0].students[0].id,country.provinces[0].cities[0].areas[0].students[0].name);
return 0;
}
这样的结构体嵌套,大家要谨慎使用,因为嵌套时内存的空间分配是成倍增加的,嵌套得越多,占用的内存就会越多,若是太大的话,系统会自我保护,自己关闭程序。
结构体传参
值传递
这样的传递方式和普通变量一样,形参的改变不会影响实参的变化,所以这样的方式改变结构体变量的成员变量,自身不会有什么改变
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char name[50];//姓名
int id;//学号
char sex;//性别
}Student;
void Func(Student stu)
{
stu.id = 20206666;
printf("在函数内部学生的学号为:%d\n", stu.id);
}
//主函数,函数入口
int main()
{
Student stu = { "张三", 20201111 ,'f'};
Func(stu);
printf("在函数外部学生的学号为:%d\n", stu.id);
return 0;
}
址传递
这也和之前的普通变量指针传递一样,外部的改变,是会改变自身的;
另外还有一个更大的优点,那就是值传递,是会在内存中重新开辟一块空间,而结构体变量所需要的空间往往是很大的,所以,使用址传递的话,就不需要重新创建临时空间,是非常好的,节省空间时间:
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char name[50];//姓名
int id;//学号
char sex;//性别
}Student;
void Func(Student* stu)//如果需要给一个指向常量的指针则需要改为 const Student* stu;
{
stu->id = 20206666;
printf("在函数内部学生的学号为:%d\n", stu->id);
}
//主函数,函数入口
int main()
{
Student stu = { "张三", 20201111,'f' };
Func(&stu);
printf("在函数外部学生的学号为:%d\n", stu.id);
return 0;
}