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.
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:
- Đọc một số nguyên
sizetừ người dùng, biểu thị số lượng số nguyên cần cấp phát - Dùng
calloc()để cấp phát động bộ nhớ cho một mảng gồmsizesố nguyên - 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 - Nếu cấp phát thành công, in ra
Memory allocated and initialized to zero! - 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] ... - Đọc
sizegiá trị số nguyên từ người dùng và lưu chúng vào mảng đã cấp phát - In tất cả giá trị đã cập nhật theo định dạng:
Updated values: [value1] [value2] [value3] ... - Tính và in tổng tất cả giá trị theo định dạng:
Sum: [value] - Dùng
free()để giải phóng bộ nhớ - 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;
}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
1Nền tảng về con trỏ
Con trỏ là gì?Khai báo con trỏToán tử lấy địa chỉ (&)Toán tử giải tham chiếu (*)Con trỏ NULLÔn tập: kiến thức cơ bản về con trỏ4Dự án: Công cụ xử lý văn bản đơn giản
Tổng quan dự ánĐếm ký tự2Con trỏ và mảng
Tên mảng dưới dạng con trỏPhần tử mảng và con trỏPhép toán con trỏSo sánh con trỏÔn tập: duyệt mảng bằng con trỏ5Con trỏ và hàm
Truyền theo giá trịTruyền con trỏ vào hàmSửa đổi biến qua con trỏVí dụ kinh điển: hoán đổiTruyền mảng vào hàmÔn tập: đối số con trỏ hàm3Mảng ký tự và chuỗi
Chuỗi dưới dạng mảng charKý tự kết thúc nullNhập chuỗi bằng scanfDùng strlen()Dùng strcpy()Dùng strcat()Dùng strcmp()Ôn tập: các hàm xử lý chuỗi cơ bản6Quản lý bộ nhớ
Bộ nhớ ngăn xếp và bộ nhớ heapCấp phát động với malloc()Dùng sizeof() để cấp phátKiểm tra lỗi cấp phátGiải phóng bộ nhớ với free()Cấp phát với calloc()Ôn tập: Mảng động9Dự án: Nhập thông tin liên hệ đơn giản
Định nghĩa struct ContactHàm tạo liên hệTự luyện tập: Trình biên dịch C online