C语言:结构体
结构体
假设我们要记录一个学生的信息:
- 姓名(字符串)
- 学号(整数)
- 成绩(浮点数)
- 性别(字符)
如果用普通变量来存,我们需要这样写:
```c
int sno[30];
char name[30][20];
float score[30];
char sex[30];
```
这样写很麻烦,而且数据之间没有关联性。结构体就是为了解决这个问题而生的!
## 什么是结构体?
结构体就像是一个"盒子",可以把不同类型的数据打包在一起。我们可以自己定义这个盒子里装什么。
定义结构体
```c
struct student {
int sno; // 学号
char name[20]; // 姓名
float score; // 成绩
char sex; // 性别
}; // 注意这里要有分号
```
这样就定义了一个叫`student`的结构体类型,它包含4个成员。
使用结构体
定义好结构体类型后,就可以像使用int、float那样使用它了:
```c
// 定义结构体变量
struct student stu1; // 定义一个学生变量
struct student class[30]; // 定义一个学生数组
struct student *p; // 定义一个指向学生的指针
```
访问结构体成员
使用点号`.`来访问结构体成员:
```c
stu1.sno = 1001;
strcpy(stu1.name, "张三");
stu1.score = 89.5;
stu1.sex = 'M';
```
结构体初始化
可以像数组一样初始化:
```c
struct student stu2 = {1002, "李四", 92.0, 'F'};
```
结构体赋值
同类型的结构体可以直接赋值:
```c
struct student stu3 = stu2; // 把stu2的值赋给stu3
```
结构体与函数
结构体可以作为函数参数和返回值:
```c
// 打印学生信息
void printStudent(struct student s) {
printf("学号:%d 姓名:%s 成绩:%.1f 性别:%c\n",
s.sno, s.name, s.score, s.sex);
}
// 输入学生信息
void inputStudent(struct student *p) {
scanf("%d %s %f %c", &p->sno, p->name, &p->score, &p->sex);
}
```
注意:使用指针传递效率更高(`->`是指向成员的运算符)。
结构体大小
结构体的大小不是简单地把所有成员大小相加,因为存在"内存对齐"的问题。计算大小时要考虑:
1. 每个成员放在它的"自然边界"上
2. 整个结构体大小要是最大成员大小的整数倍
例如:
```c
struct demo1 {
char a; // 1字节
char b; // 1字节
int c; // 4字节
}; // 总共8字节
struct demo2 {
char a; // 1字节
int b; // 4字节
char c; // 1字节
}; // 总共12字节(因为有对齐填充)
```
共用体(union)
共用体让多个变量共享同一块内存,可以节省空间:
```c
union demo {
char a;
short b;
int c;
}; // 大小是4字节(最大的成员大小)
```
共用体常用于:
1. 节省内存空间
2. 检测电脑是大端还是小端存储
枚举(enum)
枚举用来定义一组有限的常量:
```c
enum Weekday {
MON, TUE, WED, THU, FRI, SAT, SUN
};
enum Weekday today = WED;
```
枚举让代码更易读,编译器也会做更好的检查。
实际应用
结构体非常适合用来描述复杂对象,比如:
- 学生管理系统
- 网络协议
- 游戏中的角色属性
- 图形界面中的控件
练习建议
1. 定义一个学生结构体,输入3个学生信息并计算平均分
2. 写一个函数找出成绩最高的学生
3. 使用qsort对结构体数组排序
4. 尝试用共用体检测你的电脑是大端还是小端存储
结构体是C语言中非常重要的概念,掌握了它,你就能更好地组织和管理复杂数据了!