前言
在我们日常时候中有很多东西都不能用简单的用一个整型或一个字符串来表示的,比如,一个人有体重、身高、姓名、性别、年龄等等,再比如一本书,有书名、价格、作者、出版社等等,描述这些复杂事物我们就可以用结构体来解决。(以下代码均在VS2019,X86下运行)
结构体的声明
结构的基础知识
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
结构体的声明
例如描述一个学生:
struct Stu //struct Stu是结构体变量的类型 { char name[20]; //名字 int age; //年龄 char sex[5]; //性别 char id[20]; //学号 }; //分号不能丢
我们还可以这样定义:
struct Stu { char name[20]; int age; char sex[5]; char id[20]; }s1,s2; //声明一个结构体并定义两个该结构体类型变量,s1、s2是全局变量 int main() { struct Stu s3; //s3是局部变量 struct Stu s4; //s4是局部变量 return 0; }
特殊的声明
在声明结构体的时候,可以不完全的声明。
例如:
//匿名结构体类型,不知道结构体的具体类型 struct { int a; char b; float c; }x; struct { int a; char b; float c; }a[20], * p;
上面的两个结构体在声明的时候省略掉了结构体标签。
那么问题来了,在上面代码的基础上,下面的代码合法吗?
p = &x;
警告:
编译器不知道结构体的具体类型,所以会把上面的两个声明当成完全不同的两个类型。
所以是非法的。
注意:匿名结构体要定义变量只能跟在结构体后面定义。
struct { int a; char b; float c; }x; //可以 int main() { struct y; //不行 return 0; }
结构体的自引用
在结构中包含一个类型为该结构本身的成员是否可以呢?
struct Node { int data; struct Node next; };
这样定义可以吗?
如果可行,那sizeof(struct Node)为多大?
这样不行,我们看到 struct Node 类型的结构体里定义了一个结构体 next,该结构体类型里包含了一个 int 类型和一个结构体类型,这个结构体里又有结构体……
这样无限套娃,没有停止,占用的空间无限大,这是不行的。
那我们如何来正确的自引用呢?
struct Nod { int data; struct Nod* next; //定义一个该结构体的指针,解引用即可得到该结构体 }; int main() { struct Nod n; //每次定义一个结构体都要写 struct ,有没有什么办法可以不用写呢? return 0; }
我们可以这样写:
typedef struct Nod { int data; struct Nod* next; }Node; //对前面的结构体重命名,取名为 Node int main() { Node n; return 0; }
我们再来看看下面代码:
typedef struct Nod { int data; Node* next; //在结构体内部用Node不行,因为在结构体内部时还未重命名为 Node }Node;
typedef struct Nod { int data; struct Nod* next; //应该这样写 }Node;
结构体变量的定义和初始化
有了结构体类型,那如何定义变量呢?
struct Point { int x; int y; }p1; //声明类型的同时定义变量 p1 struct Point p2; //定义结构体变量 p2 struct Point p3 = { 2, 4 }; //定义变量的同时赋初值。
struct Stu //类型声明 { char name[15]; //名字 int age; //年龄 }; struct Stu s = { "zhangsan", 20 }; //初始化
struct Node { int data; struct Point p; struct Node* next; }n1 = { 10, {4,5}, NULL }; //结构体嵌套初始化 struct Node n2 = { 20, {5, 6}, NULL };//结构体嵌套初始化