calloc adalah sepupu terdekat malloc dengan satu perbedaan krusial: memori yang dikembalikan dijamin berisi nol. Selain itu, calloc menerima dua argumen (jumlah elemen dan ukuran per elemen) sehingga secara otomatis melakukan perkalian dan overflow check—fitur yang sering diabaikan programmer ketika menulis malloc(n * sizeof(T)). Pada chapter ini kita akan membandingkan malloc dan calloc secara langsung, membuktikan perbedaan perilaku keduanya, dan membahas kapan memilih satu di atas yang lain.
Kontrak Fungsi calloc #
Fungsi calloc dideklarasikan di <stdlib.h> (ISO/IEC 9899 §7.22.3.2):
void *calloc(size_t nmemb, size_t size);Kontraknya:
- Mengalokasikan
nmemb * sizebyte — dan semua byte diisi nol. - Pemeriksaan overflow bawaan —
callocmemeriksa apakahnmemb * sizemelebihiSIZE_MAX. Bila ya,callocmengembalikanNULLtanpa mengalokasikan. - Mengembalikan
NULLbila gagal — sama denganmalloc. - Pointer memiliki alignment yang cukup untuk tipe apa pun.
Mekanisme kerja: calloc pada dasarnya memanggil malloc lalu memset(ptr, 0, total). Namun, untuk alokasi besar, glibc menggunakan trick yang lebih efisien: kernel Linux memberikan halaman nol secara lazy (lewat mmap dengan MAP_ANONYMOUS), sehingga calloc untuk blok besar tidak benar-benar menulis nol ke setiap byte—kernel menyediakan halaman yang sudah nol ketika halaman tersebut pertama kali diakses. Inilah sebabnya calloc besar kadang lebih cepat daripada malloc + memset.
Verifikasi: calloc Menghasilkan Nol #
Kita buktikan bahwa calloc benar-benar mengembalikan blok berisi nol tanpa kita perlu menulis apa pun.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n = 8;
/* calloc: 2 argumen (jumlah elemen, ukuran tiap elemen) */
int *c = calloc(n, sizeof(int));
if (c == NULL) {
fprintf(stderr, "Gagal mengalokasikan memori\n");
return 1;
}
/* Verifikasi: calloc menjamin semua byte = 0 */
int semua_nol = 1;
for (size_t i = 0; i < n; i++) {
if (c[i] != 0) {
semua_nol = 0;
break;
}
}
printf("calloc: semua elemen nol? %s\n", semua_nol ? "ya" : "tidak");
printf("Isi awal: ");
for (size_t i = 0; i < n; i++) {
printf("%d ", c[i]);
}
printf("\n");
free(c);
return 0;
}Output yang Dihasilkan:
calloc: semua elemen nol? ya
Isi awal: 0 0 0 0 0 0 0 0 Semua elemen bernilai nol tanpa kita menulisnya—berbeda dengan malloc yang isinya tak terdefinisi. Untuk struct berisi pointer, “nol” berarti NULL; untuk double, “nol” berarti 0.0 (karena IEEE 754 merepresentasikan nol sebagai byte-byte nol).
Mari kita telaah baris-baris kode di atas:
- Baris 7 (
int *c = calloc(n, sizeof(int));): alokasi dengan dua argumen—n(jumlah elemen) dansizeof(int)(ukuran per elemen).callocmengalokasikann * sizeof(int)byte dan menjamin semua byte adalah nol. - Baris 13 (
if (c[i] != 0)): memeriksa apakah ada elemen yang bukan nol. Loop ini keluar lebih awal bila ada satu elemen tidak nol, lalu mencetak “tidak”. - Baris 21 (
for (size_t i = 0; i < n; i++)): loop baca-tanpa-tulis. Padamalloc, loop ini akan mencetak garbage; padacalloc, semua elemen dijamin0.
Perbandingan Langsung: malloc vs calloc #
Kita bandingkan keduanya dalam program yang sama—alokasikan blok, isi, free, lalu alokasikan blok lain dengan ukuran sama. malloc sering memakai ulang blok yang sama dan meninggalkan garbage; calloc mengembalikan blok yang sama tetapi menjamin nol.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* Tahap 1: tulis data ke blok lalu free */
int *a = malloc(5 * sizeof(int));
if (!a) return 1;
for (int i = 0; i < 5; i++) a[i] = (i + 1) * 100;
free(a);
/* Tahap 2a: malloc -- sering pakai ulang blok yang sama */
int *m = malloc(5 * sizeof(int));
if (!m) return 1;
printf("malloc (belum diisi): %d %d %d %d %d\n",
m[0], m[1], m[2], m[3], m[4]);
free(m);
/* Tahap 2b: calloc -- menjamin semua byte = 0 */
int *c = calloc(5, sizeof(int));
if (!c) return 1;
printf("calloc(belum diisi): %d %d %d %d %d\n",
c[0], c[1], c[2], c[3], c[4]);
free(c);
return 0;
}Output yang Dihasilkan:
malloc (belum diisi): 1564975282 5 0 0 500
calloc(belum diisi): 0 0 0 0 0Blok malloc berisi garbage (1564975282, 5, 500)—sisa dari blok yang kita isi dengan 100 200 300 400 500 lalu di-free. Sebaliknya, calloc mengembalikan blok yang semua elemennya 0. Perbedaan ini sangat penting: program yang lupa menginisialisasi blok malloc akan menampilkan data acak; program yang menggunakan calloc selalu dimulai dari keadaan bersih.