动态分配结构体
本课属于 Coddy C 学习旅程的“逻辑与流程”单元。第 48 课,共 63 课。
到目前为止,你已经学会了如何在栈上创建结构体。它们存在于声明它们的作用域内,并会在该作用域结束时自动清理。但如果你需要让结构体超出其原始作用域后仍然存在,或者在编译时不知道需要多少个结构体,该怎么办?
这就是动态分配发挥作用的地方。你可以使用 malloc() 在堆上创建结构体,就像创建其他数据类型一样。关键区别在于,动态分配的结构体会一直留在内存中,直到你使用 free() 显式释放它们。
这是动态分配结构体的语法:
struct Point *ptr = malloc(sizeof(struct Point));这会在堆上分配足够的内存来容纳一个 Point 结构体,并返回指向这块内存的指针。然后,你可以使用箭头运算符访问和修改结构体成员:
ptr->x = 10;
ptr->y = 20;记得始终检查 malloc() 是否成功(是否返回非 NULL),并在使用完结构体后调用 free(ptr),以防止内存泄漏。这项技术对于构建灵活的程序至关重要,这类程序可以在运行时创建和管理数据结构。
挑战
简单创建一个 C 程序,演示如何使用 malloc() 动态分配结构体。你的程序应当:
- 定义一个名为
Car的struct,包含以下成员:- 一个整数
year,用于存储制造年份 - 一个大小为 20 的字符数组
brand,用于存储汽车品牌 - 一个大小为 25 的字符数组
model,用于存储汽车型号 - 一个浮点数
price,用于存储汽车价格 - 一个整数
mileage,用于存储汽车的里程数
- 一个整数
- 在主函数中,声明一个指向
Car结构体的指针,命名为carPtr - 使用
malloc()为一个Car结构体动态分配内存,并将返回的地址赋给carPtr - 检查内存分配是否成功:
- 如果
carPtr是NULL,打印Memory allocation failed并退出程序 - 如果分配成功,打印
Memory allocation successful
- 如果
- 读取以下输入值,并使用箭头运算符将它们赋给结构体成员:
- 读取一个整数作为年份,并使用
carPtr->year赋值 - 读取一个字符串作为品牌,并使用
carPtr->brand赋值 - 读取一个字符串作为型号,并使用
carPtr->model赋值 - 读取一个浮点数作为价格,并使用
carPtr->price赋值 - 读取一个整数作为里程数,并使用
carPtr->mileage赋值
- 读取一个整数作为年份,并使用
- 读取所有值后,使用箭头运算符进行以下计算:
- 通过用 2024 减去年份来计算汽车的车龄:
int age = 2024 - carPtr->year; - 根据车龄计算折旧率:如果车龄大于 10,将折旧率设为 0.6,否则设为 0.8
- 计算当前价值:
carPtr->price * depreciation
- 通过用 2024 减去年份来计算汽车的车龄:
- 使用箭头运算符,按照以下确切格式打印汽车信息:
Car Information:Year: [year]Brand: [brand]Model: [model]Original Price: [price]Mileage: [mileage]Age: [age] yearsCurrent Value: [current_value]
- 使用
free(carPtr)释放动态分配的内存 - 打印
Memory freed successfully
这个挑战会测试你对使用 malloc() 动态分配结构体、检查分配是否失败、通过指针和箭头运算符访问结构体成员,以及使用 free() 正确释放已分配内存的理解。你将练习结构体动态内存管理的完整生命周期。
亲手试试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TODO:在这里定义 Car 结构体
int main() {
// TODO:声明一个指向 Car 结构体的指针,命名为 carPtr
// TODO:使用 malloc() 为一个 Car 结构体分配内存
// TODO:检查内存分配是否成功
// 读取输入值
int year, mileage;
char brand[20], model[25];
float price;
scanf("%d", &year);
scanf("%s", brand);
scanf("%s", model);
scanf("%f", &price);
scanf("%d", &mileage);
// TODO:使用箭头运算符将输入值赋给结构体成员
// TODO:计算车龄、折旧额和当前价值
// TODO:按要求的格式输出汽车信息
// TODO:释放已分配的内存并输出成功消息
return 0;
}这节课包含一个小测验。开始学习即可作答,并记录你的进度。
逻辑与流程中的所有课
自己练习: C 在线编译器