{ }
C语言结构体知识点详解
编程小白的全方位指南 – 用通俗易懂的方式掌握结构体核心概念
📚 什么是结构体?
结构体是C语言中一种自定义的数据类型,它允许你将多个不同类型的变量组合在一起,形成一个新类型。
生活比喻
想象结构体就像一个”数据收纳盒”。比如”学生信息盒”里可以放学生的姓名(字符串)、学号(整数)、成绩(浮点数)等各种信息。结构体就是把相关的数据打包在一起的好方法。
struct Student {
char name[50]; // 学生姓名
int id; // 学号
float score; // 成绩
};
char name[50]; // 学生姓名
int id; // 学号
float score; // 成绩
};
🔧 如何定义结构体?
结构体定义使用struct
关键字,后面跟着结构体名称和花括号{ }包裹的成员列表:
struct 结构体名称 {
类型1 成员1;
类型2 成员2;
// … 更多成员
};
类型1 成员1;
类型2 成员2;
// … 更多成员
};
重要提示
定义结构体只是创建了一种新的数据类型模板,并不会分配内存空间。只有在声明结构体变量时,才会真正分配内存。
🛠️ 声明和使用结构体变量
定义了结构体之后,就可以像使用基本类型一样声明结构体变量:
// 定义结构体
struct Person {
char name[30];
int age;
};
// 声明结构体变量
struct Person person1; // 方式1:分开定义
struct Person person2 = {“张三”, 20}; // 初始化
// 定义结构体时同时声明变量
struct Point {
int x;
int y;
} p1, p2; // 声明两个Point变量
struct Person {
char name[30];
int age;
};
// 声明结构体变量
struct Person person1; // 方式1:分开定义
struct Person person2 = {“张三”, 20}; // 初始化
// 定义结构体时同时声明变量
struct Point {
int x;
int y;
} p1, p2; // 声明两个Point变量
🔍 访问结构体成员
使用点操作符.
来访问结构体的成员:
// 定义结构体
struct Book {
char title[50];
char author[50];
float price;
};
int main() {
struct Book book1;
// 设置成员值
strcpy(book1.title, “C语言入门”);
strcpy(book1.author, “编程大师”);
book1.price = 45.8;
// 访问成员值
printf(“书名: %s\n”, book1.title);
printf(“价格: %.2f元\n”, book1.price);
}
struct Book {
char title[50];
char author[50];
float price;
};
int main() {
struct Book book1;
// 设置成员值
strcpy(book1.title, “C语言入门”);
strcpy(book1.author, “编程大师”);
book1.price = 45.8;
// 访问成员值
printf(“书名: %s\n”, book1.title);
printf(“价格: %.2f元\n”, book1.price);
}
🧩 结构体初始化
结构体可以在声明时初始化,也可以在声明后单独初始化每个成员:
// 方式1:按顺序初始化
struct Student stu1 = {“李明”, 2023001, 92.5};
// 方式2:指定成员初始化(C99及以上)
struct Student stu2 = {
.id = 2023002,
.name = “王芳”,
.score = 88.0
};
// 方式3:单独初始化每个成员
struct Student stu3;
strcpy(stu3.name, “张伟”);
stu3.id = 2023003;
stu3.score = 76.5;
struct Student stu1 = {“李明”, 2023001, 92.5};
// 方式2:指定成员初始化(C99及以上)
struct Student stu2 = {
.id = 2023002,
.name = “王芳”,
.score = 88.0
};
// 方式3:单独初始化每个成员
struct Student stu3;
strcpy(stu3.name, “张伟”);
stu3.id = 2023003;
stu3.score = 76.5;
📦 结构体数组
结构体也可以像基本类型一样用来创建数组,用于存储多个相同结构的数据:
// 定义结构体
struct Employee {
int id;
char name[30];
float salary;
};
// 创建结构体数组并初始化
struct Employee staff[3] = {
{101, “张三”, 8500.0},
{102, “李四”, 9200.5},
{103, “王五”, 7800.0}
};
// 访问数组中的结构体成员
staff[0].salary = 9000.0; // 给张三加薪
printf(“%s的工资: %.2f\n”, staff[0].name, staff[0].salary);
struct Employee {
int id;
char name[30];
float salary;
};
// 创建结构体数组并初始化
struct Employee staff[3] = {
{101, “张三”, 8500.0},
{102, “李四”, 9200.5},
{103, “王五”, 7800.0}
};
// 访问数组中的结构体成员
staff[0].salary = 9000.0; // 给张三加薪
printf(“%s的工资: %.2f\n”, staff[0].name, staff[0].salary);
📍 结构体指针
可以创建指向结构体的指针,使用箭头操作符->
访问成员:
普通结构体变量
struct Point p = {5, 10};
p.x = 20; // 使用点操作符
p.x = 20; // 使用点操作符
结构体指针
struct Point p = {5, 10};
struct Point *ptr = &p;
ptr->x = 20; // 使用箭头操作符
// 等价于 (*ptr).x = 20;
struct Point *ptr = &p;
ptr->x = 20; // 使用箭头操作符
// 等价于 (*ptr).x = 20;
何时使用结构体指针?
1. 需要传递结构体到函数中避免复制整个结构体(提高效率)
2. 需要修改函数外部的结构体内容
3. 动态内存分配时(malloc)
🔄 结构体与函数
结构体可以作为函数参数传递,也可以作为函数返回值:
// 结构体作为函数参数(传值)
void printPoint(struct Point p) {
printf(“坐标: (%d, %d)\n”, p.x, p.y);
}
// 结构体指针作为函数参数(传址)
void movePoint(struct Point *p, int dx, int dy) {
p->x += dx;
p->y += dy;
}
// 结构体作为函数返回值
struct Point createPoint(int x, int y) {
struct Point p = {x, y};
return p;
}
void printPoint(struct Point p) {
printf(“坐标: (%d, %d)\n”, p.x, p.y);
}
// 结构体指针作为函数参数(传址)
void movePoint(struct Point *p, int dx, int dy) {
p->x += dx;
p->y += dy;
}
// 结构体作为函数返回值
struct Point createPoint(int x, int y) {
struct Point p = {x, y};
return p;
}
🎯 typedef 与结构体
使用typedef
可以为结构体创建别名,简化代码:
// 常规结构体定义
struct Person {
char name[30];
int age;
};
struct Person p1; // 每次都要写 struct Person
// 使用typedef定义
typedef struct {
char name[30];
int age;
} Person; // Person 现在是一个类型名
Person p2; // 不需要写 struct 关键字
Person people[10]; // 创建数组
struct Person {
char name[30];
int age;
};
struct Person p1; // 每次都要写 struct Person
// 使用typedef定义
typedef struct {
char name[30];
int age;
} Person; // Person 现在是一个类型名
Person p2; // 不需要写 struct 关键字
Person people[10]; // 创建数组
🧬 结构体嵌套
结构体中可以包含其他结构体成员,实现复杂数据建模:
// 定义日期结构体
typedef struct {
int year;
int month;
int day;
} Date;
// 定义学生结构体,包含日期
typedef struct {
char name[50];
Date birthday; // 嵌套结构体
float gpa;
} Student;
// 使用嵌套结构体
Student s = {
.name = “李晓明”,
.birthday = {2005, 8, 12},
.gpa = 3.7
};
// 访问嵌套成员
printf(“%s的生日: %d年%d月%d日\n”, s.name,
s.birthday.year,
s.birthday.month,
s.birthday.day);
typedef struct {
int year;
int month;
int day;
} Date;
// 定义学生结构体,包含日期
typedef struct {
char name[50];
Date birthday; // 嵌套结构体
float gpa;
} Student;
// 使用嵌套结构体
Student s = {
.name = “李晓明”,
.birthday = {2005, 8, 12},
.gpa = 3.7
};
// 访问嵌套成员
printf(“%s的生日: %d年%d月%d日\n”, s.name,
s.birthday.year,
s.birthday.month,
s.birthday.day);
💡 结构体使用场景
数据分组
将逻辑相关的数据组合在一起
复杂数据结构
构建链表、树等数据结构的基础
文件处理
结构化读写二进制文件
面向对象基础
在C中模拟类与对象