1. 结构体基础概念与定义方式
结构体是C语言中一种非常重要的复合数据类型,它允许我们将不同类型的数据组合成一个整体。在实际开发中,我们经常需要处理具有多个属性的实体,比如学生信息(包含学号、姓名、成绩等),图书信息(包含书名、作者、价格等)。结构体正是为解决这类问题而设计的。
1.1 为什么需要结构体
想象一下,如果没有结构体,我们要管理一个班级的学生信息,可能需要这样定义变量:
c复制int student_id[50];
char student_name[50][20];
float student_score[50];
这种方式存在几个明显问题:
- 数据分散,难以维护
- 添加新属性需要增加新数组
- 传递参数时需要传递多个数组
而使用结构体,我们可以这样定义:
c复制struct Student {
int id;
char name[20];
float score;
};
这样就将学生的所有信息封装在一个结构体中,大大提高了代码的可读性和可维护性。
1.2 结构体的基本定义语法
结构体定义的基本语法如下:
c复制struct 结构体标签 {
成员类型1 成员名1;
成员类型2 成员名2;
...
} 变量列表;
这里有三种常见的定义方式:
方式一:先定义结构体类型,再声明变量
c复制struct Point {
int x;
int y;
};
struct Point p1, p2; // 声明两个Point类型的变量
方式二:定义结构体类型的同时声明变量
c复制struct Point {
int x;
int y;
} p1, p2; // 同时声明两个变量
方式三:使用typedef创建新类型名
c复制typedef struct {
int x;
int y;
} Point; // Point现在是一个类型名
Point p1, p2; // 可以直接使用Point声明变量
第三种方式最为常用,因为它简化了类型名的使用,避免了每次都写"struct"关键字。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 结构体的初始化与成员访问
2.1 结构体变量的初始化
结构体变量可以在定义时进行初始化,类似于数组的初始化方式:
c复制struct Student {
int id;
char name[20];
float score;
};
// 初始化方式一:按顺序提供所有成员的值
struct Student stu1 = {1001, "张三", 89.5};
// 初始化方式二:指定成员初始化(C99标准支持)
struct Student stu2 = {
.id = 1002,
.score = 92.0,
.name = "李四"
};
// 初始化方式三:先声明后逐个赋值
struct Student stu3;
stu3.id = 1003;
strcpy(stu3.name, "王五");
stu3.score = 85.5;
注意:字符串赋值需要使用strcpy函数,不能直接用等号赋值,因为数组名是常量指针。
2.2 结构体成员的访问
访问结构体成员有两种方式:
- 对于普通结构体变量,使用点运算符(.)
- 对于结构体指针,使用箭头运算符(->)
c复制struct Student stu = {1001, "张三", 89.5};
struct Student *p = &stu;
// 通过变量访问
printf("ID: %d\n", stu.id);
printf("Name: %s\n", stu.name);
// 通过指针访问
printf("ID: %d\n", p->id);
printf("Name: %s\n", p->name);
// 等价于
printf("ID: %d\n", (*p).id);
printf("Name: %s\n", (*p).name);
在实际编程中,箭头运算符更为常用,特别是在函数参数传递和动态内存分配时。
3. 结构体的高级用法
3.1 结构体嵌套
结构体可以包含其他结构体作为其成员,这种特性称为结构体嵌套。这在描述复杂数据结构时非常有用。
c复制typedef struct {
int year;
int month;
int day;
} Date;
typedef struct {
int id;
char name[20];
Date birthday; // 嵌套Date结构体
float score;
} Student;
// 初始化嵌套结构体
Student stu = {
1001,
"张三",
{20
