Variabel kontrol loop (counter) adalah jantung dari setiap loop. Walau terlihat sepele, pemilihan tipe data, scope, dan pola update counter yang tepat berpengaruh besar pada kebenaran, keterbacaan, dan keamanan kode. Salah pilih tipe dapat memicu bug off-by-one, warning compiler, atau bahkan undefined behavior seperti integer overflow. Pada chapter ini kita akan menelaah scope variabel yang dideklarasikan di dalam for, pemilihan tipe data untuk counter, serta idiom size_t untuk indeks array yang menjadi standar industri di kode C modern.
Scope Variabel di dalam for #
Sejak C99, kita diperbolehkan mendeklarasikan variabel langsung di dalam init clause for. Variabel seperti ini hanya hidup di dalam blok for—tidak dapat diakses setelah loop selesai. Pembatasan scope ini mengurangi risiko salah pakai variabel di luar loop dan membuat compiler dapat melakukan optimasi lebih agresif:
#include <stdio.h>
int main(void) {
for (int i = 0; i < 3; i = i + 1) {
int kuadrat = i * i;
printf("i=%d, kuadrat=%d\n", i, kuadrat);
}
/* Baris berikut akan compile error jika di-uncomment karena i dan kuadrat
sudah keluar dari scope: */
/* printf("i setelah loop: %d\n", i); */
printf("Loop selesai, i tidak dapat diakses lagi di sini\n");
return 0;
}Output yang Dihasilkan:
i=0, kuadrat=0
i=1, kuadrat=1
i=2, kuadrat=4
Loop selesai, i tidak dapat diakses lagi di siniMari kita telaah baris-baris kode di atas:
- Baris 4 (
for (int i = 0; i < 3; i = i + 1)): variabelidideklarasikan dan diinisialisasi langsung di dalamfor. Scopeiterbatas pada blokforsaja. - Baris 5 (
int kuadrat = i * i;): variabelkuadratdideklarasikan di dalam body loop.kuadratdihidupkan dan dimatikan pada setiap iterasi—setiap iterasi mendapat salinankuadratyang segar. - Baris 6 (
printf(...)): mencetak nilaiidankuadratpada iterasi saat ini. - Baris 11 (komentar tentang
isetelah loop): baris ini dikomentari karena akan memicu compile error. Setelah loop selesai,idankuadratsudah keluar dari scope dan tidak dapat dipakai.
Pemilihan Tipe untuk Counter #
Pilihan tipe data counter bergantung pada rentang nilai dan konteks pemakaian:
| Konteks | Tipe yang Disarankan | Alasan |
|---|---|---|
| Iterasi array berukuran kecil hingga besar | size_t | Tipe standar untuk ukuran dan indeks; tidak mungkin negatif. |
| Counter umum dengan rentang kecil (0..1000) | int | Sederhana, kompatibel dengan kebanyakan API. |
| Counter dengan rentang sangat besar | long atau long long | Menghindari overflow pada iterasi panjang. |
| Loop hitung mundur dari nilai positif | int | Memungkinkan counter mencapai -1 sebagai sentinel keluar. |
Untuk indeks array, size_t adalah pilihan terbaik karena tipe ini didefinisikan sebagai unsigned integer yang cukup besar untuk menampung indeks array terbesar yang dapat dialokasikan sistem. Operator sizeof juga menghasilkan size_t, sehingga idiom sizeof(arr)/sizeof(arr[0]) cocok secara tipe dengan counter size_t:
#include <stdio.h>
int main(void) {
int data[] = {10, 20, 30, 40, 50};
size_t n = sizeof(data) / sizeof(data[0]);
long total = 0;
for (size_t i = 0; i < n; i = i + 1) {
total = total + data[i];
}
printf("Jumlah elemen: %zu\n", n);
printf("Total: %ld\n", total);
return 0;
}Output yang Dihasilkan:
Jumlah elemen: 5
Total: 150Pada contoh di atas, n bertipe size_t karena hasil sizeof adalah size_t. Counter i juga bertipe size_t agar perbandingan i < n tidak memicu warning -Wsign-compare (membandingkan signed dengan unsigned). Format specifier %zu adalah specifier khusus untuk size_t di printf.
Jebakan Counter Unsigned saat Hitung Mundur #
Salah satu jebakan klasik dengan counter unsigned adalah loop hitung mundur. Banyak pemula menulis for (unsigned i = n - 1; i >= 0; i = i - 1) dengan asumsi loop akan berhenti saat i menjadi -1. Asumsi ini salah—unsigned tidak pernah negatif, sehingga i >= 0 selalu true, dan loop berjalan tanpa henti:
#include <stdio.h>
int main(void) {
unsigned int n = 5;
/* Loop berjalan mundur dari 4 sampai 0 */
for (unsigned int i = n - 1; i < n; i = i - 1) {
printf("i = %u\n", i);
}
printf("Setelah loop\n");
return 0;
}Output yang Dihasilkan:
i = 4
i = 3
i = 2
i = 1
i = 0
Setelah loopPada contoh di atas, kita tidak memakai i >= 0 sebagai kondisi (yang akan menjadi infinite loop), melainkan memakai idiom i < n. Saat i = 0 dan dikurangi satu, nilai i wrap-around menjadi UINT_MAX (sekitar 4 miliar), yang mana UINT_MAX < 5 adalah false—loop berhenti. Idiom ini adalah trik standar untuk hitung mundur dengan unsigned.
Konvensi Penamaan Counter #
Meskipun C tidak memaksakan aturan penamaan, beberapa konvensi telah menjadi standar industri:
i,j,kuntuk counter loop biasa (terutama di nested loops).idxatauindexuntuk indeks array yang bermakna.row,coluntuk iterasi matriks.nuntuk jumlah elemen (seringsize_t).countuntuk penghitung jumlah iterasi atau jumlah item yang diproses.
Pilih nama yang mencerminkan peran variabel dalam konteks kode. Nama i cocok untuk loop pendek dan jelas konteksnya; nama seperti baris_produk lebih cocok saat loop mengiterasi baris tabel produk di mana makna indeks penting.