一、结构体类型的声明
1.结构的声明
结构体声明的模板:
struct tag { member-list; }variable-list;
这是一个模板的声明,得出来的结构体只是一种类型,与int char一样。
例如,我们需要描述一个学生的信息,能用int类型来描述学生吗?显然是不行的,因为学生包括了学号(char),名字(char),年龄(int)和性别(char),所以这不是一个单一的类型,就需要用到结构体来描述该学生。
第一种声明方式:这个结构体的全名为:strcut Stu
struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 };//这里的分号不能丢
第二种方式:重命名
typedef struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }Stu;//给结构体类型重新取名为Stu
重新命名的方式还可以这样:
struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }; typedef struct Stu Stu;//重新起一行来命名
第三种方式:在声明的时候创造变量
struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }S1;//这里的S1是结构体创造出来的全局变量
上面一系列的操作都只是对一个结构体类型进行了声明而已,更多内容尽在后面。
2.结构体成员的类型
前言:在上面的模板我们可以知道,member_list是结构体成员,那结构体成员的类型可以是哪些呢?
结构的成员可以是标量、数组、指针,甚至是其他结构体。
struct A { char c; int a; }; struct B { char b; int arr[10]; struct A c;//成员为其他结构体成员 struct A* F;//为指针类型 };
但是需要注意的是,结构体成员不可以是本身的结构体,但是可以是本身结构体指针。
3.结构体变量的创建和初始化
在前面的时候,我们有介绍过在声明的时候创造的全局变量,接下来都一起介绍了。
第一种创造方式:
#include<stdio.h> struct Stu { char c; int arr[10]; }; int main() { struct Stu A;//结构体变量A struct Stu B;//结构体变量B return 0; }
这里创造的变量A和B都是局部变量。
第二种创造方式:
#include<stdio.h> typedef struct Stu { char c; int arr[10]; }Stu;//对结构体重命名 int main() { //struct Stu A;//结构体变量A //struct Stu B;//结构体变量B Stu C;//结构体变量C return 0; }
第三种方式:上面提到过的创造全局变量
#include<stdio.h> struct Stu { char c; int arr[10]; }D;//全局变量D int main() { //struct Stu A;//结构体变量A //struct Stu B;//结构体变量B //Stu C;//结构体变量C return 0; }
在创建后变量后,就该对变量进行初始化了
初始化:
#include<stdio.h> struct Stu { char name[20]; int age; double height; }; int main() { struct Stu s1 = {"zhangsan",20,182.8};//顺序初始化 struct Stu s2 = {.age=18,.height=188.5};//指定成员初始化 return 0; }
在创建变量的时候就初始化:
struct Stu { char name[20]; int age; double height; }s3 = {"lisi",19,150.6};//创造的全局变量并初始化
二、结构体成员的访问
当完成结构体的声明、结构体变量的创建和初始化后,就可以使用结构体了,这就是涉及到结构体成员访问的知识。
结构体的访问有两个操作符:'.'操作符和'->'操作符
接下来我们通过初始化和打印的两个操作来举例说明结构体成员访问的例子。
#include<stdio.h> struct Stu { double height; int age; }; void set_s1(struct Stu* ps)//用结构体类型指针接收 { ps->age = 22; ps->height = 188.45;//用"->"操作符访问结构体成员 } void print(struct Stu s) { printf("%d %lf",s.age,s.height); } int main() { struct Stu s1 = { 0 };//这里先初始化成0 //用一个函数对结构体变量赋值 set_s1(&s1);//因为需要修改值,所以必须要传址 //用一个函数打印结构体变量中的数据 print(s1);//只需要打印,不需要修改。传值就可以 return 0; }
我们看一下运行的结果:
在上面的例子中,出现了两个操作符,具体什么时候用哪个我们总结一下。(.和->)
结构体变量.成员名 结构体指针->成员名
就是在用指针的时候,左边必须是->,另一个同样的道理。
通过上面的例子我们可以知道,结构体既可以传值,也可以传地址,接下来我们一起看看这两个的差异吧。
1.传参
传参的话,需要重新开辟的空间很会很大,并且有的情况下传值是不能达成要求的,因为形参是实参的一份拷贝
2.传址
传址可以适用于所有的情况,并且所需要重新开辟的内存不大,所以尽可能使用结构体传址的方法。