Episode ini membuat program C berjalan di banyak platform: menulis kode portabel dengan standar C terbaru, conditional compilation untuk Windows, Linux, dan macOS, memakai library lintas platform dengan build portability, serta testing di banyak arsitektur.

Janji C adalah portability: kode yang ditulis sekali, dikompilasi di mana saja. Kenyataannya, sistem operasi berbeda memiliki API yang berbeda untuk hal yang sama. Episode 20 mengajarkan cara menepati janji tersebut secara praktis.
Fondasinya adalah mematuhi standar C. Kode yang hanya memakai fitur standar — termasuk <stdint.h>, <string.h>, dan library standar — berjalan di semua platform tanpa modifikasi. Perbedaan hanya muncul saat menyentuh API sistem.
Untuk perbedaan itu, C menyediakan conditional compilation, dan untuk build, CMake menangani perbedaan platform secara terpusat. Terakhir, testing di banyak arsitektur membuktikan janji portability dengan bukti nyata.
Tipe dasar int dan long ukurannya bisa berbeda antar platform. Untuk kode portabel, gunakan tipe dari <stdint.h> yang ukuran dan tandanya dijamin:
#include <stdint.h>
#include <stdio.h>
int main(void) {
int64_t total = 0;
uint32_t id = 100;
printf("id: %" PRIu32 "\n", id);
return 0;
}int64_t dan uint32_t dijamin ukurannya tetap di semua platform. Perhatikan PRIu32 pada format string — macro ini menyesuaikan spesifikasi format untuk platform yang memakai int atau long. Memakai macro ini menghindari warning format di 32-bit.
Kompilasi dengan -std=c17 dan -pedantic memastikan kode hanya memakai fitur standar. Fungsi seperti snprintf sudah ada di standar C99 dan portabel. Hindari fungsi non-standar seperti strcpy_s dan _sopen yang hanya ada di Windows kecuali memakai lapisan abstraksi.
Saat kode harus memakai API spesifik sistem, pisahkan dengan direktif preprocessor. Contoh membedakan pembersihan layar:
#ifdef _WIN32
#define BERSIHKAN "cls"
#else
#define BERSIHKAN "clear"
#endif
#include <stdio.h>
int main(void) {
printf("perintah: %s\n", BERSIHKAN);
return 0;
}Blok #ifdef _WIN32 memilih definisi berdasarkan platform. _WIN32 terdefinisi otomatis oleh compiler MSVC dan MinGW, sementara platform POSIX memakai cabang else. Macro ini didokumentasikan oleh compiler dan tidak boleh didefinisikan manual.
Lebih baik lagi: sembunyikan perbedaan platform di balik fungsi sendiri. Satu header mendeklarasikan antarmuka, dan file implementasi terpisah per platform dipilih saat build. Kalian akan melihat pola ini dipakai library besar; CMake memilih file mana yang dikompilasi.
Memakai library lintas platform lewat CMake menghindari manajemen library manual. find_package mencari library terpasang dan menautkannya secara portabel:
cmake_minimum_required(VERSION 3.20)
project(app LANGUAGES C)
find_package(Threads REQUIRED)
add_executable(app main.c)
target_link_libraries(app PRIVATE Threads::Threads)find_package(Threads REQUIRED) menemukan library thread dengan nama portabel, dan Threads::Threads menautkannya tanpa menebak flag -pthread atau -lpthread per platform. Inilah kekuatan CMake: perbedaan platform diselesaikan di satu tempat.
Batasi dependensi sistem seminimal mungkin. Semakin banyak API sistem yang dipakai langsung, semakin banyak titik yang harus dicabangkan dengan #ifdef. Library seperti libuv atau SDL menyediakan API lintas platform untuk I/O, jaringan, dan windowing sehingga kalian tidak menulis #ifdef sendiri.
Jalankan test yang sama di beberapa sistem operasi untuk membuktikan portability. GitHub Actions memungkinkan matriks job:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}Matriks os: [ubuntu-latest, macos-latest, windows-latest] menjalankan pipeline yang sama di tiga sistem. Error yang hanya muncul di satu platform ditemukan sebelum pengguna menemukannya.
Selain sistem operasi, arsitektur berbeda punya perbedaan endianness dan alignment. QEMU memungkinkan menjalankan binary arsitektur lain di mesin kalian, dan toolchain silang dari episode 19 membangunnya. Kombinasi keduanya memvalidasi kode untuk ARM sebelum deploy ke target nyata.
Warning
Jalankan test di semua target sebelum rilis. Kode yang lolos di Linux tetapi gagal di Windows adalah hal biasa; perbedaan termasuk urutan byte file, path separator, dan perilaku baris baru.
Inti yang harus dibawa pulang:
<stdint.h>.Di episode 21 selanjutnya kita akan membahas embedded dan low-level systems — C untuk embedded dan bare-metal programming, startup code, linker script, dan memory map, real-time constraints dan deterministik behavior, hingga debugging embedded dengan JTAG dan simulator.