Menu
CoddyTech

Cấp phát động cho cấu trúc

Thuộc phần Logic và luồng điều khiển trong hành trình C của Coddy. Bài học 48 trên 63.

Đến nay, bạn đã học cách tạo struct trên ngăn xếp, chúng tồn tại trong phạm vi khai báo và được tự động dọn dẹp khi phạm vi đó kết thúc. Nhưng nếu bạn cần một struct tồn tại lâu hơn phạm vi ban đầu, hoặc không biết trước khi biên dịch mình sẽ cần bao nhiêu struct thì sao?

Đây là lúc cấp phát động phát huy tác dụng. Bạn có thể dùng malloc() để tạo các struct trên heap, giống như với mọi kiểu dữ liệu khác. Điểm khác biệt chính là các struct được cấp phát động vẫn nằm trong bộ nhớ cho đến khi bạn giải phóng chúng bằng free().

Đây là cú pháp để cấp phát động một struct:

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

Lệnh này cấp phát đủ bộ nhớ trên heap để chứa một cấu trúc (struct) Point và trả về con trỏ đến vùng nhớ đó. Sau đó, bạn có thể dùng toán tử mũi tên để truy cập và sửa đổi các thành viên của cấu trúc:

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

Luôn kiểm tra xem malloc() có thành công hay không (có trả về giá trị khác NULL không), và gọi free(ptr) khi dùng xong struct để tránh rò rỉ bộ nhớ. Kỹ thuật này rất cần thiết để xây dựng các chương trình linh hoạt có thể tạo và quản lý cấu trúc dữ liệu trong thời gian chạy.

challenge icon

Thử thách

Dễ

Tạo một chương trình C minh họa cách cấp phát động cho cấu trúc bằng malloc(). Chương trình cần:

  1. Định nghĩa một cấu trúc struct tên là Car với các thành viên sau:
    • Một số nguyên year để lưu năm sản xuất
    • Một mảng ký tự brand có kích thước 20 để lưu thương hiệu xe
    • Một mảng ký tự model có kích thước 25 để lưu mẫu xe
    • Một số thực price để lưu giá xe
    • Một số nguyên mileage để lưu quãng đường xe đã đi
  2. Trong hàm main, khai báo một con trỏ đến cấu trúc Car có tên carPtr
  3. Dùng malloc() để cấp phát động bộ nhớ cho một cấu trúc Car và gán địa chỉ trả về cho carPtr
  4. Kiểm tra việc cấp phát bộ nhớ có thành công không:
    • Nếu carPtr là NULL, in ra Memory allocation failed rồi thoát chương trình
    • Nếu cấp phát thành công, in ra Memory allocation successful
  5. Đọc các giá trị đầu vào sau và gán chúng cho các thành viên của cấu trúc bằng toán tử mũi tên:
    • Đọc một số nguyên cho năm và gán bằng carPtr->year
    • Đọc một chuỗi cho thương hiệu và gán bằng carPtr->brand
    • Đọc một chuỗi cho mẫu xe và gán bằng carPtr->model
    • Đọc một số thực cho giá và gán bằng carPtr->price
    • Đọc một số nguyên cho quãng đường đã đi và gán bằng carPtr->mileage
  6. Sau khi đọc tất cả giá trị, thực hiện các phép tính sau bằng toán tử mũi tên:
    • Tính tuổi của xe bằng cách lấy 2024 trừ đi năm: int age = 2024 - carPtr->year;
    • Tính tỷ lệ khấu hao dựa trên tuổi xe: nếu tuổi xe lớn hơn 10, đặt khấu hao là 0.6, nếu không thì đặt là 0.8
    • Tính giá trị hiện tại: carPtr->price * depreciation
  7. In thông tin xe bằng toán tử mũi tên theo đúng định dạng sau:
    • Car Information:
    • Year: [year]
    • Brand: [brand]
    • Model: [model]
    • Original Price: [price]
    • Mileage: [mileage]
    • Age: [age] years
    • Current Value: [current_value]
  8. Giải phóng bộ nhớ đã cấp phát động bằng free(carPtr)
  9. In ra Memory freed successfully

Thử thách này kiểm tra mức độ hiểu của bạn về cấp phát động cho cấu trúc bằng malloc(), kiểm tra lỗi cấp phát, truy cập các thành viên của cấu trúc thông qua con trỏ bằng toán tử mũi tên và giải phóng đúng cách bộ nhớ đã cấp phát bằng free(). Bạn sẽ thực hành toàn bộ vòng đời quản lý bộ nhớ động với cấu trúc.

Tự làm thử

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// TODO: Định nghĩa struct Car tại đây

int main() {
    // TODO: Khai báo con trỏ đến struct Car có tên carPtr
    
    // TODO: Dùng malloc() để cấp phát bộ nhớ cho một struct Car
    
    // TODO: Kiểm tra xem việc cấp phát bộ nhớ có thành công không
    
    // Đọc các giá trị đầu vào
    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: Gán các giá trị đầu vào cho các thành viên của struct bằng toán tử mũi tên
    
    // TODO: Tính tuổi xe, mức khấu hao và giá trị hiện tại
    
    // TODO: In thông tin xe theo định dạng yêu cầu
    
    // TODO: Giải phóng bộ nhớ đã cấp phát và in thông báo thành công
    
    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Logic và luồng điều khiển

Tự luyện tập: Trình biên dịch C online