C17 (ISO/IEC 9899:2018, kadang disebut C18 berdasarkan tahun publikasi ISO) adalah standar C yang paling singkat fungsinya: tidak menambahkan satu fitur bahasa baru pun. C17 dirilis semata-mata untuk mengumpulkan defect report (DR) yang dikumpulkan komite WG14 sejak C11—klarifikasi wording, perbaikan definisi memory model, dan obsolete marking untuk fitur yang segera dihapus di C23. Bab ini memperlihatkan bagaimana kode C11 yang sama dapat dikompilasi dengan -std=c17 tanpa perubahan apa pun, lalu menunjukkan beberapa macro penting yang menjadi baseline portabilitas modern: __STDC_VERSION__ = 201710L, __STDC_NO_ATOMICS, __STDC_NO_THREADS, dan status ATOMIC_VAR_INIT yang sudah obsolete. Kita juga akan melihat mengapa C17 sering menjadi pilihan default untuk compiler modern.

C17: Standar Tanpa Fitur Baru #

Ketika komite WG14 menerbitkan C17 pada Oktober 2018, dokumen standar hanya berisi klarifikasi terhadap C11—tidak ada keyword baru, tidak ada header baru, tidak ada tipe baru. Perubahan utamanya adalah:

  • Klarifikasi wording untuk _Static_assert, _Alignas, dan anonymous struct/union.
  • Definisi ulang alokasi VLA agar tidak lagi menjadi undefined behavior saat ukuran berubah.
  • ATOMIC_VAR_INIT ditandai obsolete karena inisialisasi _Atomic int x = 0; langsung sudah cukup aman sejak C11.
  • Penegasan __has_include sebagai feature test macro yang diperlakukan sebagai predefined macro.

Program berikut memperlihatkan bahwa kode yang sama dapat dikompilasi dengan -std=c11 atau -std=c17 dan menghasilkan perilaku yang sama—perbedaan hanya pada nilai __STDC_VERSION__.

c
// File: c17_1.c - C17 adalah bugfix release; tidak ada fitur baru
#include <stdio.h>
#include <stdatomic.h>

int main(void) {
    // __STDC_VERSION__ untuk C17 adalah 201710L
#ifdef __STDC_VERSION__
    printf("__STDC_VERSION__ : %ldL\n", __STDC_VERSION__);
#endif

    // _Static_assert masih ada (ditambah C11, diperbaiki wording di C17)
    _Static_assert(sizeof(char) == 1, "char harus 1 byte");

    // _Atomic masih bekerja sama seperti C11
    _Atomic int x = 0;
    atomic_fetch_add(&x, 42);
    printf("x setelah atomic_fetch_add : %d\n", x);
    return 0;
}

Compile dan jalankan dengan kedua flag:

bash
gcc -std=c11 -Wall -Wextra -pedantic -o c17_1_c11 c17_1.c && ./c17_1_c11
gcc -std=c17 -Wall -Wextra -pedantic -o c17_1_c17 c17_1.c && ./c17_1_c17

Output yang Dihasilkan (gcc -std=c11):

text
__STDC_VERSION__ : 201112L
x setelah atomic_fetch_add : 42

Output yang Dihasilkan (gcc -std=c17):

text
__STDC_VERSION__ : 201710L
x setelah atomic_fetch_add : 42

Satu-satunya perbedaan output adalah nilai __STDC_VERSION__ (201112L vs 201710L). Perilaku runtime identik karena C17 tidak menambahkan fitur baru.

Macro Feature Test di C17 #

C11 memperkenalkan dua macro feature test opsional: __STDC_NO_ATOMICS dan __STDC_NO_THREADS. Jika compiler tidak mendukung atomics atau threads.h, macro tersebut harus didefinisikan. C17 menegaskan bahwa compiler modern wajib mendefinisikan macro ini (atau tidak) secara konsisten. Program berikut memeriksa keduanya dan status ATOMIC_VAR_INIT:

c
// File: c17_2.c - Macro feature test C17
#include <stdio.h>
#include <stdatomic.h>

int main(void) {
    printf("C17 (ISO/IEC 9899:2018) hanya berisi perbaikan defect report.\n");

    // ATOMIC_VAR_INIT: masih ada di C17 tetapi obsolete
#ifdef ATOMIC_VAR_INIT
    printf("ATOMIC_VAR_INIT terdefinisi : ya (obsolete di C17)\n");
#else
    printf("ATOMIC_VAR_INIT terdefinisi : tidak\n");
#endif

    // __STDC_NO_ATOMICS dan __STDC_NO_THREADS (opsional di C11/C17)
#ifdef __STDC_NO_ATOMICS
    printf("__STDC_NO_ATOMICS  : defined (atomics TIDAK didukung)\n");
#else
    printf("__STDC_NO_ATOMICS  : tidak defined (atomics didukung)\n");
#endif

#ifdef __STDC_NO_THREADS
    printf("__STDC_NO_THREADS  : defined (threads.h TIDAK didukung)\n");
#else
    printf("__STDC_NO_THREADS  : tidak defined (threads.h didukung)\n");
#endif

    // Penggunaan ATOMIC_VAR_INIT (cara lama, obsolete di C17)
    _Atomic int counter_old = ATOMIC_VAR_INIT(0);
    // Cara baru yang lebih sederhana
    _Atomic int counter_new = 0;

    atomic_fetch_add(&counter_old, 10);
    atomic_fetch_add(&counter_new, 5);
    printf("counter_old : %d\n", counter_old);
    printf("counter_new : %d\n", counter_new);
    return 0;
}

Compile dan jalankan:

bash
gcc -std=c17 -Wall -Wextra -pedantic -o c17_2 c17_2.c
./c17_2

Output yang Dihasilkan:

text
C17 (ISO/IEC 9899:2018) hanya berisi perbaikan defect report.
ATOMIC_VAR_INIT terdefinisi : ya (obsolete di C17)
__STDC_NO_ATOMICS  : tidak defined (atomics didukung)
__STDC_NO_THREADS  : tidak defined (threads.h didukung)
counter_old : 10
counter_new : 5

Mari kita telaah baris-baris kode di atas:

  1. Baris 11-14 (#ifdef ATOMIC_VAR_INIT ... #endif): Macro ATOMIC_VAR_INIT diperkenalkan di C11 sebagai cara portabel menginisialisasi _Atomic variable: _Atomic int x = ATOMIC_VAR_INIT(0);. Di C17, macro ini ditandai obsolete karena _Atomic int x = 0; langsung sudah terdefinisi memiliki perilaku atomic initialization yang sama.
  2. Baris 17-22 (#ifdef __STDC_NO_ATOMICS ... #endif): Jika compiler mendefinisikan macro ini, berarti compiler tersebut tidak mendukung stdatomic.h. Di GCC, Clang, dan MSVC modern, macro ini tidak didefinisikan, yang berarti atomics didukung penuh. Compiler embedded tertentu (mis. SDCC) mungkin mendefinisikannya.
  3. Baris 24-29 (#ifdef __STDC_NO_THREADS ... #endif): Sama seperti atomics, tetapi untuk threads.h. GCC/Clang mendukung threads.h via pthread. MSVC tidak menyertakan threads.h—tetapi MSVC juga tidak mendefinisikan __STDC_NO_THREADS secara konsisten, sehingga kita tidak bisa mengandalkan macro ini di MSVC.
  4. Baris 32 (_Atomic int counter_old = ATOMIC_VAR_INIT(0);): Cara lama inisialisasi atomic. Masih sah di C17 tetapi akan dihapus di C23. Compiler mungkin mengeluarkan warning -Wdeprecated saat kode ini dipakai.
  5. Baris 34 (_Atomic int counter_new = 0;): Cara baru yang sejak awal C11 sebenarnya sudah cukup. Standar C11 awal ambigu apakah ini atomic initialization; C17 mengklarifikasi bahwa ini sah dan setara dengan ATOMIC_VAR_INIT(0).

Kapan Memilih C17 #

C17 sering disebut “standar stabil” karena tidak menambahkan fitur baru, sehingga compiler modern dapat mematuhinya tanpa risiko implementasi setengah-jadi. GCC sejak versi 8, Clang sejak versi 6, dan MSVC sejak versi 2019 16.8 mendukung C17 penuh. Untuk proyek yang membutuhkan baseline stabil dan kompatibilitas maksimum antar compiler (termasuk Windows), -std=c17 adalah pilihan terbaik. Bab berikutnya akan membahas C23 yang menambahkan nullptr, constexpr, dan attribute [[nodiscard]]/[[deprecated]]—lompatan fitur terbesar sejak C11.