第十四章 结构体(一):结构体的定义与声明、结构体变量的初始化与访问、结构体数组

好,咱们今天聊聊结构体。说实话,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};

.成员名 的方式指定,顺序可以打乱。我个人比较喜欢这种方式,因为可读性强。你一看就知道哪个值赋给了哪个成员。

我曾经踩过的坑:初始化时成员个数不能少于结构体定义的成员数。比如你只给了两个值,剩下的成员会被自动初始化为 0(或空字符串)。但如果你给了超过定义个数的值,编译器会报错。所以,要么给全,要么用指定初始化

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、温度、湿度、时间戳。用结构体数组来存,遍历、查找、排序都非常方便。你想想看,要是用三个独立的数组来存,代码得多乱?

核心要点:
  • 结构体把相关数据打包,提高代码可维护性
  • 定义类型时别忘了末尾分号
  • 初始化时注意成员顺序,或用指定初始化提高可读性
  • 访问成员用 . 运算符
  • 结构体数组是处理批量结构化数据的利器

下面这张图,帮你理清本章的知识脉络:

结构体(一)知识体系 结构体 定义与声明 初始化 成员访问 先定义类型,再声明变量 定义类型同时声明变量 匿名结构体(不推荐) 按成员顺序初始化 指定成员初始化(推荐) 使用 . 运算符 字符串用 strcpy 赋值 结构体数组:批量处理结构化数据

结构体是C语言里组织数据的核心手段。掌握了它,你就能写出更清晰、更易维护的代码。别小看这个“打包”的动作,好的数据结构设计,往往能让后续的逻辑实现事半功倍。


公众号:蓝海资料掘金营,微信 deep3321