Menu
CoddyTech

Cấp phát với calloc()

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 36 trên 63.

Mặc dù malloc() là hàm phổ biến nhất để cấp phát bộ nhớ động, C còn có một lựa chọn hữu ích khác: calloc(). Hàm calloc(), viết tắt của "contiguous allocation", giúp bạn cấp phát bộ nhớ cho mảng một cách thuận tiện và có thêm một lợi ích quan trọng.

Khác với malloc(), hàm nhận một đối số (tổng số byte), calloc() nhận hai đối số: số phần tử bạn muốn cấp phát và kích thước của mỗi phần tử. Cách này đặc biệt trực quan khi làm việc với mảng. Ví dụ:

#include <stdlib.h>

// Cấp phát bộ nhớ cho 5 số nguyên bằng calloc()
int *arr = (int*)calloc(5, sizeof(int));

// Tương đương với: malloc(5 * sizeof(int))

Ưu điểm chính của calloc() là hàm này tự động khởi tạo toàn bộ vùng nhớ đã cấp phát thành 0. Khi bạn dùng malloc(), vùng nhớ đã cấp phát chứa các giá trị ngẫu nhiên từng được lưu ở đó, nhưng calloc() đảm bảo mọi byte đều được đặt thành 0. Điều này có nghĩa là mọi số nguyên đều có giá trị 0, mọi số thực đều có giá trị 0.0 và mọi con trỏ đều có giá trị NULL.

Giống như malloc(), calloc() trả về con trỏ đến vùng nhớ đã cấp phát hoặc NULL nếu cấp phát thất bại, vì vậy bạn luôn nên kiểm tra xem việc cấp phát có thất bại hay không và nhớ free() vùng nhớ khi dùng xong.

challenge icon

Thử thách

Dễ

Viết chương trình C minh họa cách dùng calloc() để cấp phát bộ nhớ động với khả năng tự động khởi tạo về 0. Chương trình cần:

  1. Đọc một số nguyên size từ người dùng, biểu thị số lượng số nguyên cần cấp phát
  2. Dùng calloc() để cấp phát động bộ nhớ cho một mảng gồm size số nguyên
  3. Kiểm tra xem việc cấp phát bộ nhớ có thành công không. Nếu thất bại, in ra Memory allocation failed! rồi kết thúc chương trình
  4. Nếu cấp phát thành công, in ra Memory allocated and initialized to zero!
  5. In tất cả giá trị ban đầu trong mảng để cho thấy chúng bằng 0, theo định dạng: Initial values: [value1] [value2] [value3] ...
  6. Đọc size giá trị số nguyên từ người dùng và lưu chúng vào mảng đã cấp phát
  7. In tất cả giá trị đã cập nhật theo định dạng: Updated values: [value1] [value2] [value3] ...
  8. Tính và in tổng tất cả giá trị theo định dạng: Sum: [value]
  9. Dùng free() để giải phóng bộ nhớ
  10. In Memory freed! để xác nhận đã dọn dẹp

Nhớ thêm tiêu đề <stdlib.h> để dùng calloc() và free(). Thử thách này minh họa ưu điểm chính của calloc() so với malloc(): tự động khởi tạo toàn bộ vùng nhớ được cấp phát về 0.

Ví dụ, nếu đầu vào là:

3
10 20 30

Đầu ra cần là:

Memory allocated and initialized to zero!
Initial values: 0 0 0
Updated values: 10 20 30
Sum: 60
Memory freed!

Thử thách này cho thấy calloc() tạo ra trạng thái ban đầu rõ ràng và nhất quán cho các mảng được cấp phát động, loại bỏ những giá trị rác khó đoán mà malloc() có thể để lại.

Tự làm thử

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

int main() {
    int size;
    
    // Đọc kích thước của mảng
    scanf("%d", &size);
    
    // TODO: Viết code của bạn bên dưới
    // Dùng calloc() để cấp phát bộ nhớ cho mảng
    // Kiểm tra xem việc cấp phát có thành công không
    // In ra các giá trị ban đầu (phải bằng 0)
    // Đọc và lưu các giá trị đầu vào
    // In ra các giá trị đã cập nhật
    // Tính và in ra tổng
    // Giải phóng bộ nhớ đã cấp phát
    
    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