结构体是一种构造类型,它右若干成员组成。其成员可以是一个基本数据类型,也可以是另一个构造类型,申明一个结构体的过程就是创建一种新的类型名的过程。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//申明结构体
struct person
{
char sex;
int age;
};
int main()
{
//定义结构体类型变量
struct person p; //这里的struct person是结构体类型名,而p是结构体变量名称
//对结构体成员进行赋值
p.sex = 's';
p.age = 22;
//使用结构体成员的值
printf("%c ,%d", p.sex, p.age);
//结构体申明的同时赋初值,
struct MyStruct
{
int age;
char name[10];
} p2 = {22,"xianming"}; //这里的每一个数据都与结构的成员相对应
//使用结构体成员的值
printf("%s ,%d", p2.name, p2.age);
//结构体数组
struct MyStruct2
{
int age;
char name[10];
}st[2]; //结构体数组名称叫st,数组个数是两个结构体
//初始化结构体数组
st[0] = {22,"zhangsan"};
st[1] = {29,"lisi"};
//结构体数组也可以在申明的同时初始化
struct MyStruct3
{
int age;
char name[10];
}str[2]{ {23,"qq"},{29,"WQ"}};
//结构体数组的数据访问方式
printf("%s ,%d", str[0].name, str[0].age);
printf("%s ,%d", str[1].name, str[1].age);
//结构体指针
struct MyStruct3* ms; //申明一个结构体指针
//结构体指针访问元素的方式1: 使用 指针*运算符
printf("%s,%d", (*ms).name, (*ms).age); //因为符号.的优先级高,故需要把 *ms 加上括号
//结构体指针访问元素的方式2: 使用 指向运算符 ->
printf("%s,%d", ms->name, ms->age);
/*
总结:
以下三种结构体的访问方式完全等价
p2.name
(*ms).name
ms->name
*/
//指向结构体数组的指针
struct MyStruct3* MS;
MS = str; //将结构体指针指向结构体数组
//遍历结构体数组
for (int i = 0; i < 2; i++,MS++) //循环的同时,让结构体指针也同步自增
{
printf("%s ,%d", MS->name, MS->age);
}
return 0;
}
结构体作为函数参数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//结构体数组也可以在申明的同时初始化
struct SD
{
int age;
char name[10];
}str = { 23,"qq" };
//结构体作为函数参数
void add(struct SD stu ) {
printf("%s, %d", stu.name, stu.age);
}
//使用结构体指针作为参数
void sum(struct SD* sd) {
printf("%s, %d", sd->name, sd->age);
}
int main()
{
add(str); //使用把结构体作为参数的函数,并把结构体传入
sum(&str); //使用把结构体指针作为参数的函数,并把结构体传入
return 0;
}
嵌套的结构体
嵌套是指结构体的成员不只普通变量,还可以是结构体。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//结构体数组也可以在申明的同时初始化
struct SD
{
int age;
char name[10];
//结构体内嵌结构体
struct mstr
{
char habby[20];
int ID;
}ms; //给内部结构体命名
}str = { 23,"qq",{"打篮球",34}}; //统一给内部结构体赋值时需要大括号
int main()
{
//访问嵌套的结构体 : str.ms.habby ,访问格式为外部结构体名称.内部结构体名称.内部结构体的成员名称
printf("name: %s,age: %d, habby: %s, ID: %d",str.name,str.age,str.ms.habby,str.ms.ID);
return 0;
}
链表
链表是一种常见的数据结构,链表中有一个头指针指向一个变量,这个变量成为元素。在链表中每个元素包含数据部分和指针部分。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//使用结构体来实现链表: 每个元素都包含数据和指针两部分,指针用于链接下一个结构体
struct Student
{
int Number;
char name[10];
struct Student* PNext;// 用于保存下一个节点的指针(下一个结构体)
};
/*
动态分配内存空间需要使用到的三个函数:
void *malloc (int size) :用于在内存中动态分配一块size大小的内存空间。分配成功返回指针,否则返回NULL.
void *calloc (unsigned n, unsigned size) :在内存中动态分配n个长度为size的连续内存空间。分配成功返回指针(该指针指向分配成功的内存首地址),否则返回NULL.
void free (void *p) :释放p指针指向的内存区,free函数无返回值。
*/
共用体
共用体也称为联合体,它使几种不同类型的变量存放到同一段内存单元中。共用体在某一时刻只能有一个值(某个数据成员的值),共用体的大小等于最大成员的大小。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//定义一个共用体
union Sex
{
char girl;
char boy;
}sex = {'x'}; //共用体变量初始化时,只需要一个初始值就够了。
int main()
{
sex.boy = 'y'; //共用体改变其中一个成员的值,其他成员也随之改变,因为他们的值的每一个二进制位都被新值覆盖。
sex.girl = 'x';
printf("%c,%c", sex.boy, sex.girl);
sex.boy = 'x';
sex.girl = 'y';
printf("%c,%c", sex.boy, sex.girl);
return 0;
}
使用共用体注意事项:
- 共用体可用来存放不同类型的成员,但每次只能存放一种类型,也就是只有一个成员能够起作用。
- 共用体中起作用的永远是最后存放的成员。
- 共用体变量的地址和它的各成员变量的地址是一样的。
- 不能对共用体变量名赋值,也不能企图引用变量名来得到一个值。
枚举类型
枚举类型是一种基本数据类型,不能再被分拆,一个枚举变量包含一组相关的标识符,每个标识符都对应一个整数值,称为枚举常量。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//枚举只是一系列标识符常量,其底层实际上真正使用的是标识符对应的数字
//定义一个枚举,括号中第一个标识符对应数字0,后面的标识符依次递增,也可以手动设置其值。
enum Colors{red, green, blue} ;
//enum Color2{red=1, green, blue}; //第一个元素设置为1之后,其后的值默认依次递增1
int main()
{
Colors color=red;//初始化枚举变量,默认设置为第一个标志
printf("%s",color); //打印的结果是0
switch (color)
{
case red:
printf("红色"); //输出红色
break;
case green:
printf("绿色");
break;
case blue:
printf("蓝色");
break;
}
return 0;
}