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.
| Tahun | Nama | Kode Standar | Sorotan Fitur |
|---|---|---|---|
| 1978 | K&R C | buku Brian Kernighan & Dennis Ritchie | Tidak ada prototipe fungsi; /* */ komentar |
| 1989 | C89 / ANSI C | ANSI X3.159-1989 | Prototipe fungsi, void, void *, const, volatile |
| 1990 | C90 / ISO C90 | ISO/IEC 9899:1990 | Sama dengan C89, hanya diadopsi ISO verbatim |
| 1995 | C95 | ISO/IEC 9899:1990/Amd 1:1995 | wchar_t, wctype.h, wchar.h, trigraph tambahan |
| 1999 | C99 | ISO/IEC 9899:1999 | // komentar, mixed declaration, VLA, stdint.h, stdbool.h, designated initializer |
| 2011 | C11 | ISO/IEC 9899:2011 | _Generic, _Static_assert, _Alignas, threads.h, stdatomic.h, anonymous struct/union, gets_s |
| 2018 | C17 / C18 | ISO/IEC 9899:2018 | Bugfix release, tidak ada fitur baru |
| 2024 | C23 | ISO/IEC 9899:2024 | nullptr, 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.
/* 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:
gcc -std=c11 -Wall -Wextra -o sejarah1 sejarah1.c
./sejarah1Output yang Dihasilkan:
__STDC__ : 1 (ISO C compliant)
__STDC_VERSION__ : 201112L
__STDC_HOSTED__ : 1 (hosted)
__GNUC__ : 14.2.0Mari kita telaah baris-baris kode di atas:
- Baris 7-10 (
#ifdef __STDC__): Macro__STDC__didefinisikan bernilai1jika compiler berjalan dalam mode ISO C. Pada mode K&R atau GNU extensions tertentu, macro ini bisa tidak terdefinisi. Kita bungkus dengan#ifdefagar aman di compiler pre-standard. - Baris 13-17 (
#ifdef __STDC_VERSION__): Nilai199409L(C95),199901L(C99),201112L(C11),201710L(C17), atau202311L(C23 final) menandakan edisi standar. Saat di-compile dengan-std=c11di GCC 14, hasilnya201112L. - Baris 20-22 (
__STDC_HOSTED__): Nilai1berarti program berjalan di lingkungan hosted (memiliki library standar penuh danmain), sedangkan0berarti freestanding (kernel, firmware) tanpa jaminanstdio.h. - 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 babconditional-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.
/* 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:
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_c23Output yang Dihasilkan (gcc -std=c99):
Standar aktif : C99
Kode numerik : 199901LOutput yang Dihasilkan (gcc -std=c17):
Standar aktif : C17
Kode numerik : 201710LOutput yang Dihasilkan (gcc -std=c2x):
Standar aktif : C23
Kode numerik : 202000LMengapa 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.