是什么结构体:
在编写程序时,我们遇到的不止有简单的变量、数学运算,当我们想要表达一个复杂的数据类型时,但是不巧的是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‘};
这样就不用再多写一行了,比较方便。
结构体变量的定义及初始化:
定义:结构体的定义有两种方法;
一种是在声明时定义:
struct Student { char name[1024];//姓名 int id;//学号 char sex;//性别 }stu1, stu2;
这种方法,我们定义了两个结构体变量,stu1,stu2,不过在这种情况下,不能使用typedef,这一点要注意;
另一种则是在使用时定义:
#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;
初始化:也有两种方法:
一种是在声明定义结合在一起时初始化:
struct Student { char name[1024];//姓名 int id;//学号 char sex;//性别 }stu1={"张三",20201111,’f‘}, stu2={"小红",20202222,‘m‘};
另一种是在使用时定义的时候初始化:
#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; }
原文:https://www.cnblogs.com/zhm521/p/13943955.html