C99 (ISO/IEC 9899:1999) adalah lompatan fitur terbesar dalam sejarah C setelah standarisasi C89. Standar ini menjawab kebutuhan praktis programmer: komentar // yang lebih ringkas, deklarasi variabel di tengah blok (mixed declaration) untuk membaca lebih dekat ke penggunaan, tipe integer dengan lebar eksak (uint32_t, int64_t) lewat header stdint.h, tipe boolean asli (bool) lewat stdbool.h, type long long 64-bit, variable-length array (VLA), designated initializer, compound literal, dan inline function. Bab ini menunjukkan setiap fitur tersebut dengan kode yang di-compile menggunakan gcc -std=c99 -pedantic, agar kita yakin kode benar-benar memakai C99 murni dan bukan ekstensi GCC. Kita juga akan melihat bagaimana fitur-fitur ini mengubah gaya penulisan C dari gaya verbose C89 menjadi lebih ringkas dan ekspresif.

Komentar //, Mixed Declaration, dan Designated Initializer #

Tiga perubahan paling terasa dari C89 ke C99 adalah sintaksis keseharian: komentar satu baris //, deklarasi variabel di mana pun di dalam blok, dan designated initializer yang memungkinkan kita menyebut field struct berdasarkan nama saat inisialisasi. Ketiganya membuat kode jauh lebih ringkas dan membaca lebih dekat ke penggunaan variabel.

c
// File: c99_1.c - Fitur khas C99: // komentar, mixed declaration, designated initializer
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

typedef struct {
    char nama[32];
    int  umur;
    bool lulus;
} Siswa;

int main(void) {
    // designated initializer: sebut field by name
    Siswa daftar[3] = {
        [0] = { .nama = "Budi", .umur = 17, .lulus = true },
        [1] = { .nama = "Siti", .umur = 18, .lulus = true },
        [2] = { .nama = "Andi", .umur = 16, .lulus = false }
    };

    printf("%-6s %-4s %s\n", "Nama", "Umur", "Lulus");
    printf("%-6s %-4s %s\n", "----", "----", "-----");
    for (int i = 0; i < 3; ++i) {        // deklarasi i di dalam for
        printf("%-6s %-4d %s\n",
            daftar[i].nama,
            daftar[i].umur,
            daftar[i].lulus ? "ya" : "tidak");
    }

    // Tipe integer width-exact dari stdint.h
    uint32_t harga = 1500000u;
    int64_t  populasi_dunia = 7900000000LL;
    printf("\nHarga         : %u\n", harga);
    printf("Populasi dunia: %lld\n", (long long)populasi_dunia);
    return 0;
}

Compile dan jalankan:

bash
gcc -std=c99 -Wall -Wextra -pedantic -o c99_1 c99_1.c
./c99_1

Output yang Dihasilkan:

text
Nama   Umur Lulus
----   ---- -----
Budi   17   ya
Siti   18   ya
Andi   16   tidak

Harga         : 1500000
Populasi dunia: 7900000000

Mari kita telaah baris-baris kode di atas:

  1. Baris 1 (// File: c99_1.c ...): Komentar satu baris dengan //, ilegal di C89 tetapi sah di C99. Tanpa -std=c99, GCC menerima // sebagai ekstensi; dengan -std=c89 -pedantic komentar ini akan jadi error.
  2. Baris 15-19 (Siswa daftar[3] = { [0] = {...}, [1] = {...}, [2] = {...} };): Designated initializer. Kita sebut index array [0], [1], [2] dan field struct .nama, .umur, .lulus secara eksplisit. Inisialisasi tidak perlu mengikuti urutan field, dan field yang tidak disebut otomatis di-zero.
  3. Baris 24 (for (int i = 0; ...)): Deklarasi int i di dalam statement for. Di C89, i harus dideklarasikan di awal blok main. C99 mengizinkan deklarasi di mana pun dalam blok, termasuk di dalam clause for.
  4. Baris 33 (uint32_t harga = 1500000u;): Tipe integer dengan lebar eksak 32-bit dari stdint.h. Di C89, kita hanya punya int, long, short yang lebarnya bergantung platform. Dengan uint32_t, kode portable dijamin ukurannya.
  5. Baris 34 (int64_t populasi_dunia = 7900000000LL;): Tipe long long 64-bit baru di C99, dengan literal LL. Tanpa LL, angka sebesar 7.9 miliar tidak muat di 32-bit int dan akan terpotong.

VLA dan Compound Literal #

Variable-Length Array (VLA) memungkinkan array dengan ukuran yang baru diketahui saat runtime, diambil dari variabel biasa. Compound literal memungkinkan kita membuat struct atau array tanpa nama variabel, langsung di ekspresi. Kedua fitur ini membuat C99 lebih fleksibel untuk kode numerik dan prototyping cepat.

c
// File: c99_2.c - VLA dan compound literal
#include <stdio.h>

static int jumlah_vla(int n) {
    int buf[n];                  // VLA: ukuran dari variabel runtime
    for (int i = 0; i < n; ++i) {
        buf[i] = i * i;
    }
    int total = 0;
    for (int i = 0; i < n; ++i) {
        total += buf[i];
    }
    return total;
}

int main(void) {
    int n = 5;
    printf("Jumlah kuadrat 0..%d: %d\n", n - 1, jumlah_vla(n));

    // compound literal: membuat struct sementara in-place
    struct Koord { int x; int y; };
    struct Koord titik = (struct Koord){ .x = 3, .y = 4 };
    printf("Titik: (%d, %d), jarak^2 = %d\n",
        titik.x, titik.y, titik.x * titik.x + titik.y * titik.y);

    // compound literal untuk array
    int *arr = (int[]){10, 20, 30, 40};
    for (int i = 0; i < 4; ++i) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    return 0;
}

Compile dan jalankan:

bash
gcc -std=c99 -Wall -Wextra -pedantic -o c99_2 c99_2.c
./c99_2

Output yang Dihasilkan:

text
Jumlah kuadrat 0..4: 30
Titik: (3, 4), jarak^2 = 25
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40

Fungsi jumlah_vla menerima parameter n dan membuat array lokal buf[n] dengan ukuran yang baru diketahui saat pemanggilan. VLA disimpan di stack dengan ukuran dinamis—ini berbeda dengan malloc yang menggunakan heap. VLA nyaman untuk buffer sementara yang ukurannya kecil dan hanya hidup dalam satu fungsi. Compound literal (struct Koord){ .x = 3, .y = 4 } dan (int[]){10, 20, 30, 40} membuat objek tanpa harus mendeklarasikan variabel terlebih dahulu—berguna untuk passing argumen ke fungsi yang menerima pointer.

Inline Function dan long long #

C99 formalisasi keyword inline (sebelumnya ekstensi C++ di banyak compiler) dan menambahkan tipe long long (minimal 64-bit). Program berikut memperlihatkan keduanya:

c
// File: c99_3.c - inline function dan long long
#include <stdio.h>

static inline int kuadrat(int x) {
    return x * x;
}

int main(void) {
    long long besar = 9000000000LL;   // 64-bit integer literal
    printf("Kuadrat 7      : %d\n", kuadrat(7));
    printf("Long long besar: %lld\n", besar);
    return 0;
}

Compile dan jalankan:

bash
gcc -std=c99 -Wall -Wextra -pedantic -o c99_3 c99_3.c
./c99_3

Output yang Dihasilkan:

text
Kuadrat 7      : 49
Long long besar: 9000000000

Keyword inline memberi tahu compiler bahwa pemanggilan fungsi kuadrat dapat diganti dengan badan fungsi secara langsung (inlined) untuk efisiensi. Tipe long long menjamin minimal 64-bit, sedangkan literal 9000000000LL diakhiri LL agar diproses sebagai long long. Pada arsitektur 32-bit lama, int hanya 32-bit sehingga angka 9 miliar tidak muat—long long menyelesaikan ini tanpa kode platform-specific.