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.

c
#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:

text
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:

  1. Baris 6 (int *a = malloc(5 * sizeof(int));): malloc menerima jumlah byte, karenanya kita kalikan 5 dengan sizeof(int). Memori yang dikembalikan tidak diinisialisasi—isi bisa berupa sampah.
  2. Baris 9 (int *b = calloc(5, sizeof(int));): calloc menerima dua argumen: jumlah elemen dan ukuran tiap elemen. Selain mengalokasikan, calloc juga mengenol-kan semua byte. Cocok untuk array yang harus mulai dari nol.
  3. Baris 14 (int *a_baru = realloc(a, 10 * sizeof(int));): realloc mengubah ukuran blok. Bisa saja mengembalikan pointer baru (bila blok lama tidak bisa diperbesar in-place), sehingga data lama disalin secara otomatis. Bila realloc gagal, pointer lama a tetap valid—makanya kita simpan dulu ke a_baru, bukan langsung ke a.
  4. Baris 16 (a = a_baru;): baru setelah realloc pasti sukses, kita ganti pointer lama dengan yang baru. Tanpa pola ini, kegagalan realloc akan menyebabkan memory leak karena a hilang.
  5. Baris 26-27 (free(a); free(b);): setiap malloc/calloc/realloc yang sukses wajib diikuti free. 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.

c
#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:

text
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) = 42

Fungsi 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.

c
#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:

text
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 = 1

Mengambil 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.