Header <stdlib.h> adalah “ruang serbaguna” standard library C. Header ini mengelola empat area yang saling berbeda: alokasi memori dinamis (malloc, calloc, realloc, free), konversi string ke angka (atoi, strtol, strtod), kontrol program (exit, abort, atexit), dan utilitas umum (qsort, rand, abs). Hampir setiap program C yang membutuhkan heap atau pengurutan pasti mengandalkan <stdlib.h>. Pada chapter ini kita akan meninjau fungsi-fungsi paling sering dipakai beserta jebakan klasiknya.
Alokasi Memori: malloc, calloc, realloc, free #
Empat fungsi ini mengelola heap—area memori dinamis yang bertahan hidup lebih luar dari stack frame fungsi. malloc mengalokasikan blok mentah tanpa inisialisasi, calloc mengalokasikan dan mengenol-kan, realloc mengubah ukuran blok yang sudah ada, sedangkan free mengembalikan blok ke heap.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* malloc: alokasi tanpa inisialisasi */
int *a = malloc(5 * sizeof(int));
if (a == NULL) { perror("malloc"); return 1; }
/* calloc: alokasi + nol-kan */
int *b = calloc(5, sizeof(int));
if (b == NULL) { perror("calloc"); return 1; }
for (int i = 0; i < 5; i++) a[i] = i * 10;
/* realloc: ubah ukuran blok yang sudah ada */
int *a_baru = realloc(a, 10 * sizeof(int));
if (a_baru == NULL) { free(a); perror("realloc"); return 1; }
a = a_baru;
for (int i = 5; i < 10; i++) a[i] = i * 10;
printf("Array a (malloc+realloc): ");
for (int i = 0; i < 10; i++) printf("%d ", a[i]);
printf("\n");
printf("Array b (calloc) : ");
for (int i = 0; i < 5; i++) printf("%d ", b[i]);
printf("\n");
free(a);
free(b);
return 0;
}Output yang Dihasilkan:
Array a (malloc+realloc): 0 10 20 30 40 50 60 70 80 90
Array b (calloc) : 0 0 0 0 0 Mari kita telaah baris-baris kode di atas:
- Baris 6 (
int *a = malloc(5 * sizeof(int));):mallocmenerima jumlah byte, karenanya kita kalikan5dengansizeof(int). Memori yang dikembalikan tidak diinisialisasi—isi bisa berupa sampah. - Baris 9 (
int *b = calloc(5, sizeof(int));):callocmenerima dua argumen: jumlah elemen dan ukuran tiap elemen. Selain mengalokasikan,callocjuga mengenol-kan semua byte. Cocok untuk array yang harus mulai dari nol. - Baris 14 (
int *a_baru = realloc(a, 10 * sizeof(int));):reallocmengubah ukuran blok. Bisa saja mengembalikan pointer baru (bila blok lama tidak bisa diperbesar in-place), sehingga data lama disalin secara otomatis. Bilareallocgagal, pointer lamaatetap valid—makanya kita simpan dulu kea_baru, bukan langsung kea. - Baris 16 (
a = a_baru;): baru setelahreallocpasti sukses, kita ganti pointer lama dengan yang baru. Tanpa pola ini, kegagalanreallocakan menyebabkan memory leak karenaahilang. - Baris 26-27 (
free(a); free(b);): setiapmalloc/calloc/reallocyang sukses wajib diikutifree. Pasangan ini seperti open/close pada file.
Konversi String ke Angka: atoi vs strtol #
Fungsi atoi mengkonversi string ke int tetapi tidak melaporkan kesalahan. Bila input bukan angka, atoi mengembalikan 0—sulit membedakan dari input "0" yang valid. Fungsi strtol memberi kontrol lebih baik lewat parameter endptr.
#include <stdio.h>
#include <stdlib.h>
/* Comparator untuk qsort: mengurutkan int menaik */
static int banding_int(const void *p1, const void *p2) {
int a = *(const int *)p1;
int b = *(const int *)p2;
return (a > b) - (a < b); /* aman dari overflow */
}
int main(void) {
int data[] = {42, 7, 19, 100, 3, 88, 56};
size_t n = sizeof(data) / sizeof(data[0]);
printf("Sebelum: ");
for (size_t i = 0; i < n; i++) printf("%d ", data[i]);
printf("\n");
qsort(data, n, sizeof(int), banding_int);
printf("Setelah : ");
for (size_t i = 0; i < n; i++) printf("%d ", data[i]);
printf("\n");
/* atoi vs strtol: strtol bisa deteksi error */
const char *s1 = "123";
const char *s2 = "99budi";
const char *s3 = "bukan_angka";
printf("\natoi(\"%s\") = %d\n", s1, atoi(s1));
printf("atoi(\"%s\") = %d (error tidak terdeteksi!)\n", s2, atoi(s2));
printf("atoi(\"%s\") = %d (error tidak terdeteksi!)\n", s3, atoi(s3));
/* strtol: endptr untuk validasi */
char *endp = NULL;
long v = strtol(s2, &endp, 10);
printf("\nstrtol(\"%s\"): nilai=%ld, sisa=\"%s\"\n", s2, v, endp);
/* abs */
printf("\nabs(-42) = %d\n", abs(-42));
return 0;
}Output yang Dihasilkan:
Sebelum: 42 7 19 100 3 88 56
Setelah : 3 7 19 42 56 88 100
atoi("123") = 123
atoi("99budi") = 99 (error tidak terdeteksi!)
atoi("bukan_angka") = 0 (error tidak terdeteksi!)
strtol("99budi"): nilai=99, sisa="budi"
abs(-42) = 42Fungsi qsort adalah algoritma quicksort generik dari standard library. Fungsi ini menerima pointer void * ke elemen pertama, jumlah elemen, ukuran tiap elemen, dan sebuah comparator function yang membandingkan dua elemen lewat const void *. Pola return (a > b) - (a < b); menghasilkan -1, 0, atau 1 tanpa risiko overflow yang mungkin terjadi pada return a - b;. Fungsi strtol mengisi endp dengan pointer ke karakter pertama yang tidak ikut diparse—di contoh, endp menunjuk ke "budi". Bila endp sama dengan pointer awal string, berarti tidak ada karakter angka valid sama sekali.
Random Number dan Kontrol Program #
Fungsi rand menghasilkan bilangan pseudo-random int dalam rentang 0 sampai RAND_MAX. Fungsi srand memberi seed; bila tidak dipanggil, seed default 1 dipakai sehingga urutan random selalu sama. Untuk aplikasi nyata, biasanya kita pakai srand((unsigned)time(NULL)) agar urutan berubah setiap program dijalankan. Untuk deterministic test seperti di buku, kita pakai seed tetap.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
/* srand: beri seed tetap agar output reproducible di buku */
srand(42);
printf("Lima angka acak 0..99 (seed=42):\n");
for (int i = 0; i < 5; i++) {
printf(" rand() = %d -> mod 100 = %d\n", rand(), rand() % 100);
}
/* Demo exit vs abort - di sini kita tunjukkan EXIT_SUCCESS */
printf("\nMenggunakan EXIT_SUCCESS = %d\n", EXIT_SUCCESS);
printf("Menggunakan EXIT_FAILURE = %d\n", EXIT_FAILURE);
return EXIT_SUCCESS;
}Output yang Dihasilkan:
Lima angka acak 0..99 (seed=42):
rand() = 708592740 -> mod 100 = 66
rand() = 907283241 -> mod 100 = 81
rand() = 537146758 -> mod 100 = 12
rand() = 1854614940 -> mod 100 = 21
rand() = 53523743 -> mod 100 = 35
Menggunakan EXIT_SUCCESS = 0
Menggunakan EXIT_FAILURE = 1Mengambil rand() % 100 untuk angka 0..99 cukup untuk demo, tetapi bias modulo membuat distribusi tidak rata bila RAND_MAX + 1 bukan kelipatan 100. Untuk kebutuhan kriptografi atau statistik serius, gunakan sumber random dari sistem operasi (misalnya membaca /dev/urandom di Linux). Konstanta EXIT_SUCCESS (0) dan EXIT_FAILURE (1) adalah cara portabel mengembalikan exit status dari main, lebih jelas dibanding literal 0 atau 1.