第十四章 结构体(一):结构体的定义与声明、结构体变量的初始化与访问、结构体数组
好,咱们今天聊聊结构体。说实话,C语言里要是没有结构体,那写起代码来可真叫一个难受。我记得刚入行那会儿,接手一个老项目,里面全是散落的变量——学生姓名一个数组、年龄一个数组、成绩又一个数组。维护起来简直要命。后来我重构了一遍,全换成结构体,整个世界都清净了。
结构体是什么?说白了,就是把一堆不同类型的数据打包成一个整体。你想想看,一个学生有姓名、年龄、成绩,这三个东西类型都不一样,但逻辑上它们属于同一个实体。结构体就是干这个的。
14.1 结构体的定义
定义结构体,用的是 struct 关键字。语法其实不复杂:
struct 结构体名 {
数据类型 成员1;
数据类型 成员2;
// ...
}; // 注意这个分号,不能丢
举个例子,定义一个学生类型:
struct Student {
char name[20];
int age;
float score;
};
嗯,这里要注意:struct Student 是一个类型,不是变量。它就像一张蓝图,告诉编译器“以后凡是这种类型的数据,都长这样”。
14.2 结构体变量的声明
定义完结构体,怎么用它?声明变量呗。有三种方式:
方式一:先定义类型,再声明变量
struct Student stu1;
struct Student stu2;
这是最常用的方式。类型定义一次,变量想声明多少个都行。
方式二:定义类型的同时声明变量
struct Student {
char name[20];
int age;
float score;
} stu1, stu2;
这种方式适合“这个类型我就用一两次,不打算复用”。
方式三:匿名结构体
struct {
char name[20];
int age;
float score;
} stu1, stu2;
连结构体名都省了。但注意,这种方式不能再声明新的变量了。我在项目中见过有人这么写,后来想扩展,发现没法引用这个类型,只能重写一遍。所以,除非你确定只用这一次,否则别偷这个懒。
14.3 结构体变量的初始化
声明完变量,总得给个初值吧?C语言提供了几种初始化方式。
方式一:按成员顺序初始化
struct Student stu1 = {"张三", 20, 89.5};
花括号里的值,按结构体定义的成员顺序一一对应。简单直接。
方式二:指定成员初始化(C99 起支持)
struct Student stu2 = {.name = "李四", .score = 92.0, .age = 21};
用 .成员名 的方式指定,顺序可以打乱。我个人比较喜欢这种方式,因为可读性强。你一看就知道哪个值赋给了哪个成员。
14.4 结构体成员的访问
访问结构体成员,用 . 运算符。语法很简单:
结构体变量名.成员名
看个完整例子:
#include <stdio.h>
#include <string.h>
struct Student {
char name[20];
int age;
float score;
};
int main() {
struct Student stu1 = {"张三", 20, 89.5};
// 访问成员
printf("姓名:%s\n", stu1.name);
printf("年龄:%d\n", stu1.age);
printf("成绩:%.1f\n", stu1.score);
// 修改成员
stu1.age = 21;
strcpy(stu1.name, "张三丰");
stu1.score = 95.0;
printf("修改后:\n");
printf("姓名:%s\n", stu1.name);
printf("年龄:%d\n", stu1.age);
printf("成绩:%.1f\n", stu1.score);
return 0;
}
输出结果:
姓名:张三
年龄:20
成绩:89.5
修改后:
姓名:张三丰
年龄:21
成绩:95.0
注意,字符串成员不能直接赋值,得用 strcpy。这是新手最容易犯的错。
14.5 结构体数组
一个学生好办,一个班 50 个学生呢?难道声明 50 个变量?当然不。用结构体数组。
结构体数组,就是数组的每个元素都是一个结构体变量。定义方式跟普通数组一样:
struct Student class[50];
这就有了 50 个学生的空间。初始化也类似:
struct Student class[3] = {
{"张三", 20, 89.5},
{"李四", 21, 92.0},
{"王五", 19, 78.5}
};
访问时,先定位到数组元素,再访问成员:
printf("第一个学生:%s\n", class[0].name);
printf("第二个学生成绩:%.1f\n", class[1].score);
遍历整个数组,用循环:
for (int i = 0; i < 3; i++) {
printf("第%d个学生:%s,年龄%d,成绩%.1f\n",
i+1, class[i].name, class[i].age, class[i].score);
}
我在项目中处理过一批传感器数据,每个传感器有 ID、温度、湿度、时间戳。用结构体数组来存,遍历、查找、排序都非常方便。你想想看,要是用三个独立的数组来存,代码得多乱?
- 结构体把相关数据打包,提高代码可维护性
- 定义类型时别忘了末尾分号
- 初始化时注意成员顺序,或用指定初始化提高可读性
- 访问成员用
.运算符 - 结构体数组是处理批量结构化数据的利器
下面这张图,帮你理清本章的知识脉络:
结构体是C语言里组织数据的核心手段。掌握了它,你就能写出更清晰、更易维护的代码。别小看这个“打包”的动作,好的数据结构设计,往往能让后续的逻辑实现事半功倍。
公众号:蓝海资料掘金营,微信 deep3321