Menu
CoddyTech

动态分配结构体

本课属于 Coddy C 学习旅程的“逻辑与流程”单元。第 48 课,共 63 课。

到目前为止,你已经学会了如何在栈上创建结构体。它们存在于声明它们的作用域内,并会在该作用域结束时自动清理。但如果你需要让结构体超出其原始作用域后仍然存在,或者在编译时不知道需要多少个结构体,该怎么办?

这就是动态分配发挥作用的地方。你可以使用 malloc() 在堆上创建结构体,就像创建其他数据类型一样。关键区别在于,动态分配的结构体会一直留在内存中,直到你使用 free() 显式释放它们。

这是动态分配结构体的语法:

struct Point *ptr = malloc(sizeof(struct Point));

这会在堆上分配足够的内存来容纳一个 Point 结构体,并返回指向这块内存的指针。然后,你可以使用箭头运算符访问和修改结构体成员:

ptr->x = 10;
ptr->y = 20;

记得始终检查 malloc() 是否成功(是否返回非 NULL),并在使用完结构体后调用 free(ptr),以防止内存泄漏。这项技术对于构建灵活的程序至关重要,这类程序可以在运行时创建和管理数据结构。

challenge icon

挑战

简单

创建一个 C 程序,演示如何使用 malloc() 动态分配结构体。你的程序应当:

  1. 定义一个名为 Car 的 struct,包含以下成员:
    • 一个整数 year,用于存储制造年份
    • 一个大小为 20 的字符数组 brand,用于存储汽车品牌
    • 一个大小为 25 的字符数组 model,用于存储汽车型号
    • 一个浮点数 price,用于存储汽车价格
    • 一个整数 mileage,用于存储汽车的里程数
  2. 在主函数中,声明一个指向 Car 结构体的指针,命名为 carPtr
  3. 使用 malloc() 为一个 Car 结构体动态分配内存,并将返回的地址赋给 carPtr
  4. 检查内存分配是否成功:
    • 如果 carPtr 是 NULL,打印 Memory allocation failed 并退出程序
    • 如果分配成功,打印 Memory allocation successful
  5. 读取以下输入值,并使用箭头运算符将它们赋给结构体成员:
    • 读取一个整数作为年份,并使用 carPtr->year 赋值
    • 读取一个字符串作为品牌,并使用 carPtr->brand 赋值
    • 读取一个字符串作为型号,并使用 carPtr->model 赋值
    • 读取一个浮点数作为价格,并使用 carPtr->price 赋值
    • 读取一个整数作为里程数,并使用 carPtr->mileage 赋值
  6. 读取所有值后,使用箭头运算符进行以下计算:
    • 通过用 2024 减去年份来计算汽车的车龄:int age = 2024 - carPtr->year;
    • 根据车龄计算折旧率:如果车龄大于 10,将折旧率设为 0.6,否则设为 0.8
    • 计算当前价值:carPtr->price * depreciation
  7. 使用箭头运算符,按照以下确切格式打印汽车信息:
    • Car Information:
    • Year: [year]
    • Brand: [brand]
    • Model: [model]
    • Original Price: [price]
    • Mileage: [mileage]
    • Age: [age] years
    • Current Value: [current_value]
  8. 使用 free(carPtr) 释放动态分配的内存
  9. 打印 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;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

逻辑与流程中的所有课

自己练习: C 在线编译器