Compiler gcc membedakan dua tingkat keparahan pesan: error yang menghentikan kompilasi, dan warning yang hanya memberi catatan tetap mengizinkan program dibangun. Banyak bug halus—buffer overflow, format specifier salah, variabel tak terpakai—tidak secara teknis melanggar sintaks C, sehingga compiler hanya mengeluarkan warning. Membuang warning dengan alasan “tetap compile” adalah kebiasaan berbahaya: pesan-pesan tersebut hampir selalu menandai cacat nyata. Pada chapter ini kita akan mempelajari flag warning utama (-Wall, -Wextra, -Wpedantic), perilaku -Werror yang menaikkan warning menjadi error, dan cara membaca beberapa warning paling produktif (-Wunused-variable, -Wsign-compare, -Wformat, -Wreturn-type).
Tiga Flag Warning Utama #
-Wall #
Flag -Wall mengaktifkan sekumpulan warning yang dianggap paling berguna dan minim false positive. Nama “all” menyesatkan—flag ini tidak mengaktifkan seluruh warning gcc, hanya yang sudah dikurasi tim gcc sebagai aman untuk production code. Berikut beberapa warning yang masuk grup -Wall:
-Wunused-variable: variabel dideklarasikan tetapi tidak pernah dipakai.-Wunused-function: fungsistatictidak pernah dipanggil.-Wformat: format specifierprintf/scanftidak cocok dengan tipe argumen.-Wreturn-type: fungsi non-voidpunya path yang tidak mengembalikan nilai.-Wmaybe-uninitialized: variabel dipakai sebelum diberi nilai awal.
-Wextra #
-Wextra menambahkan warning yang lebih bertele-tele dan terkadang noisy pada kode lama, tetapi sangat berguna untuk kode baru. Contoh warning yang hanya aktif lewat -Wextra:
-Wsign-compare: membandingkan signed dan unsigned integer (potensi bug ketikai < ndenganibertanda danntak bertanda).-Wempty-body: bodyif/whilekosong akibat titik komaif (x); ....-Wmissing-field-initializers: struct tidak diinisialisasi penuh.-Wunused-parameter: parameter fungsi tidak dipakai.
-Wpedantic #
Flag -Wpedantic (sebelumnya -pedantic) menonaktifkan ekstensi non-standar gcc dan memunculkan warning untuk konstruksi yang secara teknis valid tetapi melanggar standar ISO C ketat. Flag ini wajib dipakai bila kita ingin kode portabel ke compiler lain (clang, MSVC, vendor compiler tertentu).
Contoh Nyata: Variabel Tak Terpakai #
/* File: /tmp/test_warn_unused.c */
#include <stdio.h>
int main(void) {
int x = 10;
int y = 20; /* tidak dipakai */
printf("x = %d\n", x);
return 0;
}Tanpa -Werror, kompilasi masih berhasil:
gcc -std=c11 -Wall -Wextra /tmp/test_warn_unused.c -o /tmp/test_warn_unusedOutput yang Dihasilkan:
/tmp/test_warn_unused.c: In function 'main':
/tmp/test_warn_unused.c:4:9: warning: unused variable 'y' [-Wunused-variable]
4 | int y = 20; /* tidak dipakai */
| ^Saat kita menambah -Werror, warning yang sama menjadi error dan kompilasi gagal:
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror /tmp/test_warn_unused.c -o /tmp/test_warn_unused2Output yang Dihasilkan:
/tmp/test_warn_unused.c: In function 'main':
/tmp/test_warn_unused.c:4:9: error: unused variable 'y' [-Werror=unused-variable]
4 | int y = 20; /* tidak dipakai */
| ^
cc1: all warnings being treated as errorsMari kita bedah perubahan kunci pada output di atas:
- Kata kunci
errormenggantikanwarning: identitas pesan berubah dari catatan menjadi galat fatal. gcc menambahkan suffix[-Werror=unused-variable]agar kita tahu warning mana yang dinaikkan tingkatnya. - Baris
cc1: all warnings being treated as errors: baris penutup dari preprocessor front-endcc1mengkonfirmasi bahwa flag-Werroraktif dan seluruh warning akan menjadi error. - gcc tidak menghasilkan binary: file
/tmp/test_warn_unused2tidak dibuat karena linking dibatalkan.
-Wsign-compare dan Jebakan Loop #
Perbandingan antara int (signed) dan size_t (unsigned) adalah sumber bug klasik. Variabel loop int i yang dibandingkan dengan sizeof(arr) akan memunculkan warning -Wsign-compare. Tanpa -Wextra, warning ini tidak muncul dan bug tetap diam-diam.
/* File: /tmp/test_warn_cmp.c */
#include <stdio.h>
#include <stddef.h>
int main(void) {
int arr[5] = {0, 1, 2, 3, 4};
size_t n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i <= n; i++) { /* bug: <= bukan < */
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}gcc -std=c11 -Wall -Wextra /tmp/test_warn_cmp.c -o /tmp/test_warn_cmpOutput yang Dihasilkan:
/tmp/test_warn_cmp.c: In function 'main':
/tmp/test_warn_cmp.c:6:23: warning: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'long unsigned int'} [-Wsign-compare]
6 | for (int i = 0; i <= n; i++) { /* bug: <= bukan < */
| ^~Pesan warning di atas membongkar dua masalah sekaligus: (1) i bertipe int sedangkan n bertipe size_t yang unsigned, dan (2) jangan gunakan <= untuk batas array karena indeks valid adalah 0..n-1. Perbaikan yang benar adalah mengubah tipe i menjadi size_t dan operator <= menjadi <:
for (size_t i = 0; i < n; i++) {
printf("%d ", arr[i]);
}-Wformat Menangkap Bug printf #
Salah satu warning paling produktif di grup -Wall adalah -Wformat yang mencocokkan format specifier (%d, %s, %f) dengan tipe argumen yang diberikan. Bug seperti printf("%d", variabel_double) sering lolos review manual karena program tetap berjalan, hanya saja mencetak angka yang salah.
/* File: /tmp/test_warn_fmt.c */
#include <stdio.h>
int main(void) {
double pi = 3.14;
printf("pi = %d\n", pi); /* bug: %d untuk double */
return 0;
}gcc -std=c11 -Wall -Wextra /tmp/test_warn_fmt.c -o /tmp/test_warn_fmtOutput yang Dihasilkan:
/tmp/test_warn_fmt.c: In function 'main':
/tmp/test_warn_fmt.c:4:19: warning: format '%d' expects argument of type 'int', but argument 2 has type 'double' [-Wformat=]
4 | printf("pi = %d\n", pi); /* bug: %d untuk double */
| ~^ ~~
| | |
| int double
| %fgcc bahkan mencetak saran %f sebagai pengganti %d — sebuah diff kecil yang bisa langsung kita terapkan.
-Wreturn-type untuk Fungsi yang Tidak Lengkap #
Standar C menyatakan bahwa fungsi non-void harus mengembalikan nilai pada setiap path eksekusi. Bila ada cabang yang lupa return, perilaku program menjadi undefined. -Wreturn-type memunculkan warning untuk kasus ini.
/* File: /tmp/test_warn_pedantic.c */
#include <stdio.h>
int fungsi_tanpa_return(int x) {
if (x > 0) {
printf("positif\n");
}
/* tidak ada return untuk path negatif */
}
int main(void) {
fungsi_tanpa_return(5);
return 0;
}gcc -std=c11 -Wall -Wextra -Wpedantic /tmp/test_warn_pedantic.c -o /tmp/test_warn_pedanticOutput yang Dihasilkan:
/tmp/test_warn_pedantic.c: In function 'fungsi_tanpa_return':
/tmp/test_warn_pedantic.c:7:1: warning: control reaches end of non-void function [-Wreturn-type]
7 | }
| ^Pesan control reaches end of non-void function menandakan ada jalur yang mencapai akhir fungsi tanpa mengeksekusi return. Perbaikan adalah menambah return 0; (atau nilai default lain) di akhir fungsi.
Kombinasi Standar Industri #
Makefile atau build script modern umumnya memakai kombinasi flag berikut sebagai standar minimum:
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror -g -O0 -o app app.cMari kita uraikan setiap flag pada perintah di atas:
-std=c11: memakai standar C11 (C ISO/IEC 9899:2011). Pilihanc17atauc23juga lazim untuk proyek baru.-Wall -Wextra -Wpedantic: tiga lapis warning utama yang dibahas di atas.-Werror: semua warning menjadi error, sehingga kompilasi gagal pada warning pertama.-g: menyertakan simbol debug (DWARF) untukgdb,addr2line, dan profiler.-O0: mematikan optimasi agar urutan baris kode sesuai dengan eksekusi mesin (penting untuk debugging).