Istilah infinite loop atau loop tanpa akhir sering diasosiasikan dengan bug—program yang “hang” karena loop tidak pernah berhenti. Namun di C, infinite loop yang ditulis dengan sengaja dan dipasangkan dengan break adalah salah satu idiom paling lazim. Banyak program event-driven seperti server, GUI, atau game memakai loop while (1) yang berjalan terus menerus sampai sinyal keluar diterima. Bahkan di program biasa, loop tanpa kondisi alami sering lebih mudah ditulis sebagai while (1) { ... if (...) break; ... } daripada loop while dengan kondisi rumit di atas. Pada chapter ini kita akan menelaah dua bentuk infinite loop yang sengaja ditulis, membedakan infinite loop yang disengaja dengan yang tidak, serta cara menguji program dengan timeout untuk keamanan.

Bentuk Infinite Loop yang Disengaja #

Ada dua idiom utama infinite loop yang disengaja di C:

  • while (1) { ... } — kondisi 1 selalu true, loop berjalan tanpa akhir.
  • for (;;) { ... } — ketiga komponen for dikosongkan, kondisi dianggap selalu true.

Kedua bentuk ini setara secara semantik. Pilihan antara keduanya biasanya gaya personal atau konvensi tim. Loop tanpa akhir seperti ini wajib memiliki setidaknya satu path break di dalam body—jika tidak, program akan benar-benar berjalan tanpa henti dan harus dimatikan secara paksa dari luar.

c
#include <stdio.h>

int main(void) {
    int pencacah = 0;

    while (1) {
        pencacah = pencacah + 1;
        if (pencacah >= 5) {
            break;
        }
        printf("Iterasi ke-%d\n", pencacah);
    }

    printf("Loop berhenti di pencacah = %d\n", pencacah);
    return 0;
}

Output yang Dihasilkan:

text
Iterasi ke-1
Iterasi ke-2
Iterasi ke-3
Iterasi ke-4
Loop berhenti di pencacah = 5

Mari kita telaah baris-baris kode di atas:

  1. Baris 5 (while (1)): kondisi 1 selalu true, sehingga loop berjalan tanpa akhir jika tidak ada break.
  2. Baris 6 (pencacah = pencacah + 1;): increment counter dilakukan lebih dulu sebelum pengecekan kondisi keluar.
  3. Baris 7 (if (pencacah >= 5)): kondisi keluar. Saat pencacah mencapai 5, break akan dieksekusi.
  4. Baris 8 (break;): keluar dari loop. Tanpa baris ini, loop tidak pernah berhenti.
  5. Baris 10 (printf(...)): hanya dieksekusi untuk pencacah bernilai 1, 2, 3, 4. Saat pencacah = 5, break melewatkan printf ini.
  6. Baris 13 (printf(...)): dieksekusi setelah loop berhenti, mencetak nilai akhir pencacah yang bernilai 5.

Idiom for (;;) #

Bentuk alternatif yang juga lazim adalah for (;;). Secara semantik, for (;;) setara dengan while (1)—kondisi kosong di for dianggap true secara default. Beberapa programmer lebih suka for (;;) karena lebih ringkas dan secara visual menandakan “loop tanpa akhir”, sementara yang lain lebih suka while (1) karena lebih eksplisit:

c
#include <stdio.h>

int main(void) {
    int i = 0;
    int total = 0;

    for (;;) {
        i = i + 1;
        total = total + i;
        if (total >= 30) {
            break;
        }
    }

    printf("Berhenti: i=%d, total=%d\n", i, total);
    return 0;
}

Output yang Dihasilkan:

text
Berhenti: i=8, total=36

Pada contoh di atas, loop menambahkan i ke total sampai total >= 30. Loop berhenti saat total = 36 (yaitu i = 8), karena pada iterasi tersebut kondisi total >= 30 pertama kali terpenuhi. Tanpa break, loop akan terus menambah tanpa henti.

Mengamankan Pengujian dengan timeout #

Saat menguji program yang berpotensi infinite loop, kita perlu memastikan program berhenti dalam waktu yang masuk akal. Perintah timeout di Linux memaksa program berhenti setelah jumlah detik tertentu, terlepas dari apakah loop sudah keluar atau belum:

c
#include <stdio.h>
#include <unistd.h>

int main(void) {
    int detik = 0;

    /* Loop sengaja tanpa akhir; keluar setelah 3 detik untuk demo */
    while (1) {
        printf("Detik ke-%d: program masih berjalan\n", detik);
        sleep(1);
        detik = detik + 1;
        if (detik >= 3) {
            break;
        }
    }

    printf("Loop dihentikan secara internal setelah %d iterasi\n", detik);
    return 0;
}

Output yang Dihasilkan:

text
Detik ke-0: program masih berjalan
Detik ke-1: program masih berjalan
Detik ke-2: program masih berjalan
Loop dihentikan secara internal setelah 3 iterasi

Program di atas menampilkan pola event-driven sederhana. Loop while (1) berjalan terus, mencetak status setiap detik dengan bantuan sleep(1), lalu keluar setelah detik mencapai 3. Saat menguji program seperti ini dari terminal, kita bisa memakai perintah timeout 5 ./program untuk memastikan program berhenti paling lama 5 detik—jika program benar-benar tidak pernah memanggil break, timeout akan mengirim sinyal SIGTERM dan mematikan proses secara paksa.

Infinite Loop yang Tidak Disengaja #

Tidak semua infinite loop disengaja. Bug paling umum adalah loop yang seharusnya berhenti tetapi tidak, karena kondisi tidak pernah menjadi false atau update counter tidak dieksekusi. Berikut beberapa penyebab klasik infinite loop yang tidak disengaja:

  1. Lupa menulis increment counter di while biasa (loop tidak memiliki cara untuk berhenti).
  2. Menempatkan increment counter setelah continue di while (increment tidak pernah dieksekusi untuk iterasi yang masuk ke continue).
  3. Memodifikasi variabel counter di tempat yang salah sehingga tidak mendekati batas kondisi.
  4. Kondisi yang tidak mungkin false karena bug logika, misalnya while (i >= 0) dengan i yang diisi unsigned dan dikurangi terus (akan wrap-around ke nilai besar, tidak pernah negatif).

Kapan Memakai Infinite Loop yang Disengaja #

Pakai while (1) atau for (;;) ketika kondisi berhenti terlalu rumit untuk dinyatakan dalam satu ekspresi kondisi di atas loop, atau ketika logika keluar bergantung pada banyak variabel yang berubah di tengah body. Contoh kasus:

  • Loop event-driven: program GUI atau server yang menunggu event sampai sinyal keluar.
  • Menu interaktif: pengguna memilih “keluar” dari menu untuk berhenti.
  • Pencarian multi-kriteria: berhenti ketika salah satu dari beberapa kondisi terpenuhi.
  • Protokol komunikasi: terus membaca pesan sampai sinyal akhir diterima.

Hindari infinite loop yang disengaja untuk loop pencacahan sederhana—for (int i = 0; i < n; i = i + 1) selalu lebih jelas daripada while (1) { ... if (i >= n) break; ... i++; }.