Bahasa C lahir pada awal 1970-an di Bell Labs sebagai bahasa implementasi Unix, dan sejak saat itu terus berkembang lewat serangkaian standar formal. Tanpa standar, kode C yang kita tulis di GCC di Linux belum tentu dapat dikompilasi di MSVC di Windows atau di compiler tertanam di mikrokontroler. Bab ini membuka section Standar dan Portabilitas dengan menelusuri rangkaian edisi standar C—mulai dari buku K&R 1978, ANSI C89 tahun 1989, ISO C90 1990, lalu C95, C99, C11, C17, hingga C23—agar kita memahami kenapa sebagian kode legacy masih menggunakan /* */ komentar, kenapa // baru tersedia secara portabel sejak C99, dan kenapa nullptr serta constexpr baru sah sebagai keyword di C23. Kita juga akan memeriksa macro __STDC_VERSION__ yang memungkinkan program mendeteksi versi standar compiler saat di-compile.

Lini Masa Standar C #

Standar C dirawat oleh dua komite: ANSI X3J11 (Amerika) di awal, lalu dilanjutkan oleh ISO/IEC JTC1/SC22/WG14 (dunia). Berikut tonggak utama yang membentuk bahasa C modern.

TahunNamaKode StandarSorotan Fitur
1978K&R Cbuku Brian Kernighan & Dennis RitchieTidak ada prototipe fungsi; /* */ komentar
1989C89 / ANSI CANSI X3.159-1989Prototipe fungsi, void, void *, const, volatile
1990C90 / ISO C90ISO/IEC 9899:1990Sama dengan C89, hanya diadopsi ISO verbatim
1995C95ISO/IEC 9899:1990/Amd 1:1995wchar_t, wctype.h, wchar.h, trigraph tambahan
1999C99ISO/IEC 9899:1999// komentar, mixed declaration, VLA, stdint.h, stdbool.h, designated initializer
2011C11ISO/IEC 9899:2011_Generic, _Static_assert, _Alignas, threads.h, stdatomic.h, anonymous struct/union, gets_s
2018C17 / C18ISO/IEC 9899:2018Bugfix release, tidak ada fitur baru
2024C23ISO/IEC 9899:2024nullptr, true/false keyword, constexpr, [[nodiscard]]/[[deprecated]], #embed, _BitInt

Standar C89 dan C90 praktis identik—C89 dipublikasikan ANSI lebih dulu, kemudian ISO mengadopsi tanpa perubahan teknis dan menerbitkannya sebagai C90. Banyak literatur menyebut keduanya bergantian. C95 adalah Amendment 1 untuk C90, bukan standar penuh, tetapi GCC dan Clang menganggapnya bagian dari c95 dialect.

Macro __STDC_VERSION__: Cara Program Mengenali Standarnya Sendiri #

Compiler C yang patuh standar ISO wajib menyediakan macro __STDC_VERSION__ (sejak C95) yang berisi nilai long berformat YYYYMML. Nilai ini memungkinkan program menulis kode kondisional yang beradaptasi dengan versi standar yang aktif. Program berikut menampilkan macro-macro standar yang tersedia di compiler kita.

c
/* File: sejarah1.c - Tampilkan standar C yang didukung compiler */
#include <stdio.h>

int main(void) {
    /* __STDC__ bernilai 1 bila compiler mematuhi standar ISO C */
#ifdef __STDC__
    printf("__STDC__            : %d (ISO C compliant)\n", __STDC__);
#else
    printf("__STDC__            : tidak terdefinisi (pre-standard)\n");
#endif

    /* __STDC_VERSION__ berisi long integer YYYYMML */
#ifdef __STDC_VERSION__
    printf("__STDC_VERSION__    : %ldL\n", __STDC_VERSION__);
#else
    printf("__STDC_VERSION__    : tidak terdefinisi (C90 mode)\n");
#endif

    /* __STDC_HOSTED__ 1 = hosted, 0 = freestanding */
#ifdef __STDC_HOSTED__
    printf("__STDC_HOSTED__     : %d (%s)\n",
        __STDC_HOSTED__, __STDC_HOSTED__ ? "hosted" : "freestanding");
#endif

    /* Versi compiler GCC */
#ifdef __GNUC__
    printf("__GNUC__            : %d.%d.%d\n",
        __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#endif
    return 0;
}

Compile dan jalankan dengan flag -std=c11 untuk mendapatkan standar C11:

bash
gcc -std=c11 -Wall -Wextra -o sejarah1 sejarah1.c
./sejarah1

Output yang Dihasilkan:

text
__STDC__            : 1 (ISO C compliant)
__STDC_VERSION__    : 201112L
__STDC_HOSTED__     : 1 (hosted)
__GNUC__            : 14.2.0

Mari kita telaah baris-baris kode di atas:

  1. Baris 7-10 (#ifdef __STDC__): Macro __STDC__ didefinisikan bernilai 1 jika compiler berjalan dalam mode ISO C. Pada mode K&R atau GNU extensions tertentu, macro ini bisa tidak terdefinisi. Kita bungkus dengan #ifdef agar aman di compiler pre-standard.
  2. Baris 13-17 (#ifdef __STDC_VERSION__): Nilai 199409L (C95), 199901L (C99), 201112L (C11), 201710L (C17), atau 202311L (C23 final) menandakan edisi standar. Saat di-compile dengan -std=c11 di GCC 14, hasilnya 201112L.
  3. Baris 20-22 (__STDC_HOSTED__): Nilai 1 berarti program berjalan di lingkungan hosted (memiliki library standar penuh dan main), sedangkan 0 berarti freestanding (kernel, firmware) tanpa jaminan stdio.h.
  4. Baris 26-28 (__GNUC__): Versi GCC spesifik, bukan bagian ISO C, tetapi berguna untuk mendeteksi ekstensi compiler. Nilai ini membantu kita menulis kode kondisional per compiler di bab conditional-feature-support.

Mendeteksi Edisi Standar Secara Programatik #

Program berikut menerjemahkan nilai __STDC_VERSION__ menjadi nama standar yang dapat dibaca. Kode ini bermanfaat untuk dijalankan di header portabilitas atau di awal main sebagai sanity check saat membangun library lintas compiler.

c
/* File: sejarah2.c - Terjemahkan __STDC_VERSION__ ke nama standar */
#include <stdio.h>

static const char *nama_standar(void) {
#if !defined(__STDC_VERSION__)
    return "C90 (atau K&R)";
#elif __STDC_VERSION__ < 199901L
    return "C95 (C90 + Amendment 1)";
#elif __STDC_VERSION__ < 201112L
    return "C99";
#elif __STDC_VERSION__ < 201710L
    return "C11";
#elif __STDC_VERSION__ < 202311L
    return "C17";
#else
    return "C23";
#endif
}

int main(void) {
    printf("Standar aktif : %s\n", nama_standar());
#ifdef __STDC_VERSION__
    printf("Kode numerik   : %ldL\n", __STDC_VERSION__);
#endif
    return 0;
}

Compile dengan beberapa flag dan amati perbedaannya:

bash
gcc -std=c99 -Wall -Wextra -o sejarah2_c99  sejarah2.c && ./sejarah2_c99
gcc -std=c17 -Wall -Wextra -o sejarah2_c17  sejarah2.c && ./sejarah2_c17
gcc -std=c2x -Wall -Wextra -o sejarah2_c23  sejarah2.c && ./sejarah2_c23

Output yang Dihasilkan (gcc -std=c99):

text
Standar aktif : C99
Kode numerik   : 199901L

Output yang Dihasilkan (gcc -std=c17):

text
Standar aktif : C17
Kode numerik   : 201710L

Output yang Dihasilkan (gcc -std=c2x):

text
Standar aktif : C23
Kode numerik   : 202000L

Mengapa Lini Masa Standar Penting bagi Kita #

Setiap kali kita menulis kode yang akan dikompilasi di banyak compiler (GCC, Clang, MSVC, vendor embedded), pemilihan standar menentukan fitur apa yang boleh dipakai. Sebagai contoh, kode yang menggunakan // komentar dan deklarasi variabel di tengah blok akan ditolak oleh compiler yang hanya mematuhi C89—itu sebabnya banyak file header proyek lama (mis. SQLite, PostgreSQL) masih menggunakan gaya C89. Sebaliknya, kode yang memakai _Generic dan _Static_assert membutuhkan minimal C11. Bab-bab berikutnya akan menelusuri setiap edisi standar satu per satu, mulai dari C90/C95 hingga C23, lalu membahas strategi memilih -std yang tepat untuk proyek kita.