Bahasa C tidak ditentukan oleh satu compiler, melainkan oleh dokumen standar internasional ISO/IEC 9899. Dokumen ini terus diperbarui oleh komite WG14 setiap beberapa tahun sekali. Pada Chapter ini kita akan menelusuri versi-versi standar C yang paling sering dijumpai, melihat fitur apa yang ditambahkan di setiap versi, dan mencoba beberapa fitur lewat contoh kode yang dikompilasi dengan flag -std yang berbeda.

Mengenal ISO/IEC 9899 #

ISO/IEC 9899 adalah standar resmi bahasa C yang dipelihara oleh komite teknis WG14 di bawah ISO. Versi-versi yang telah diterbitkan antara lain:

VersiTahunNama umumSorotan fitur
C901990ANSI C / C89baseline standar formal pertama
C991999C99komentar //, deklarasi di tengah blok, _Bool, long long, VLAs
C112011C11_Static_assert, _Generic, atomic, thread <threads.h>
C172018C17perbaikan cacat, tidak ada fitur baru signifikan
C232024C23constexpr, bool/true/false keyword, atribut [[...]], auto

Compiler GCC dan Clang menyediakan flag -std=cNN untuk memilih versi standar yang dipakai saat kompilasi. Flag ini sangat penting karena kode yang sah di C99 bisa jadi tidak sah di C89, dan sebaliknya beberapa fitur C23 belum tentu didukung compiler lama.

C99: Komentar Baris dan Deklarasi Fleksibel #

Standar C99 menambahkan dua fitur yang dipakai sehari-hari tanpa kita sadari: komentar // dan deklarasi variabel di tengah blok kode. Sebelum C99, semua deklarasi variabel harus berada di awal blok, dan komentar hanya boleh memakai pasangan /* ... */.

c
/* Komentar satu baris -- fitur C99 */
#include <stdio.h>
#include <stdbool.h>

int main(void) {
    // Deklarasi variabel di tengah blok -- fitur C99
    for (int i = 0; i < 3; i++) {
        bool genap = (i % 2 == 0);
        printf("i=%d, genap=%d\n", i, (int)genap);
    }
    return 0;
}

Output yang Dihasilkan (dengan flag -std=c99):

text
i=0, genap=1
i=1, genap=0
i=2, genap=1

Mari kita telaah baris-baris kode di atas:

  1. Baris 1 (/* ... */): komentar gaya lama, valid di semua versi C.
  2. Baris 5 (int main(void)): tanda void di parameter didefinisikan sebagai “tidak ada argumen” sejak C99; kurung kosong main() berarti “argumen tidak ditentukan”.
  3. Baris 7 (// ...): komentar satu baris gaya C++, baru sah mulai C99.
  4. Baris 8 (for (int i = 0; ...)): deklarasi i di dalam for, fitur C99.
  5. Baris 9 (bool genap = ...;): tipe _Bool dibungkus alias bool lewat header <stdbool.h>, diperkenalkan di C99.

Jika kode yang sama dikompilasi dengan flag -std=c89 -pedantic, GCC akan menolak komentar // dan deklarasi variabel di dalam for. Pesan galat yang muncul akan menyebutkan kedua fitur tersebut tidak diizinkan pada mode C89.

C11: Static Assert dan Generic Selection #

C11 menambahkan beberapa fitur yang mempermudah pemrograman generik dan pemeriksaan statis. Dua yang paling berguna bagi pemula adalah _Static_assert dan _Generic. _Static_assert memeriksa kondisi pada saat kompilasi; bila kondisi bernilai 0, kompilasi gagal dengan pesan yang kita berikan. _Generic memungkinkan satu makro memilih ekspresi berdasarkan tipe argumen, semacam function overloading terbatas.

c
#include <stdio.h>

/* _Static_assert: cek kondisi saat kompilasi -- fitur C11 */
_Static_assert(sizeof(int) >= 2, "int harus minimal 2 byte");

#define tipe(X) _Generic((X), \
    int: "int", \
    long: "long", \
    double: "double", \
    default: "lain")

int main(void) {
    int a = 5;
    long b = 10L;
    double c = 3.14;
    printf("a -> %s\n", tipe(a));
    printf("b -> %s\n", tipe(b));
    printf("c -> %s\n", tipe(c));
    return 0;
}

Output yang Dihasilkan (dengan flag -std=c11):

text
a -> int
b -> long
c -> double

Mari kita telaah baris-baris kode di atas:

  1. Baris 4 (_Static_assert(sizeof(int) >= 2, "...")): compiler mengevaluasi sizeof(int) >= 2 saat kompilasi; bila 0, kompilasi gagal dengan pesan yang ditentukan.
  2. Baris 6-10 (#define tipe(X) _Generic(...)): makro yang memakai _Generic untuk memilih string literal sesuai tipe argumen.
  3. Baris 13-15 (int a = 5; long b = 10L; double c = 3.14;): tiga variabel dengan tipe berbeda.
  4. Baris 16-18 (tipe(a), tipe(b), tipe(c)): makro diekspansi ke string yang sesuai dengan tipe setiap variabel.

C23: Konstekspresi dan Atribut #

C23 yang disetujui tahun 2024 membawa banyak fitur modern. Yang paling sering dipakai adalah keyword constexpr, atribut [[nodiscard]]/[[deprecated]]/[[noreturn]], serta bool, true, dan false yang kini menjadi keyword bawaan tanpa perlu header <stdbool.h>.

c
#include <stdio.h>

constexpr int MAX = 10;

[[nodiscard]] int hitung(void) {
    return MAX * 2;
}

int main(void) {
    bool aktif = true;          /* C23: bool/true/false jadi keyword */
    auto x = 5;                /* C23: auto berarti tipe default int */
    printf("MAX = %d\n", MAX);
    printf("hitung() = %d\n", hitung());
    printf("aktif = %d\n", (int)aktif);
    printf("x = %d\n", x);
    return 0;
}

Output yang Dihasilkan (dengan flag -std=c23):

text
MAX = 10
hitung() = 20
aktif = 1
x = 5

Mari kita telaah baris-baris kode di atas:

  1. Baris 3 (constexpr int MAX = 10;): MAX menjadi konstanta compile-time; nilainya bisa dipakai sebagai ukuran array atau label case pada switch.
  2. Baris 5 ([[nodiscard]] int hitung(void)): atribut [[nodiscard]] meminta compiler memberi peringatan bila pemanggil membuang hasil kembalian fungsi.
  3. Baris 10 (bool aktif = true;): tanpa #include <stdbool.h> karena bool, true, dan false kini keyword bawaan.
  4. Baris 11 (auto x = 5;): di C23 auto berarti tipe disimpulkan; di C lama auto berarti storage class lokal (jarang dipakai).

Memilih Standar untuk Proyek Baru #

Untuk proyek C baru, beberapa pertimbangan praktis:

  • C11 aman dipakai karena didukung semua compiler modern dan sudah mengandung _Static_assert, _Generic, serta <threads.h>.
  • C17 pilihan konservatif untuk kode produksi karena hanya berisi perbaikan cacat dari C11.
  • C23 cocok untuk proyek yang target kompilernya selalu modern (GCC 14+, Clang 18+).

Bab-bab selanjutnya dalam Course ini akan memakai flag -std=c11 karena keseimbangan antara dukungan compiler dan ketersediaan fitur modern.