Menu

Switch Case di C: Case, break, dan Fall-Through

Cara pernyataan switch di C memilih satu cabang dari daftar konstanta: label case, kenapa break itu penting, fall-through yang disengaja dan yang tidak, default, switch pada char dan enum, serta kapan switch lebih baik daripada rantai else-if.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Satu Nilai, Banyak Konstanta

Rantai else if yang terus membandingkan variabel yang sama dengan konstanta adalah pola yang punya pernyataan khusus di C:

if (choice == 1)      { /* ... */ }
else if (choice == 2) { /* ... */ }
else if (choice == 3) { /* ... */ }
else                  { /* ... */ }

switch menyatakannya dengan lebih langsung. Pernyataan ini mengevaluasi ekspresinya sekali, lalu langsung melompat ke label yang cocok.

Ubah nilai choice lalu jalankan lagi. Strukturnya membuat himpunan nilai yang sah terlihat sekilas, dan itulah alasan sebenarnya untuk memilihnya di sini.

Sintaks dan Aturan Label Case

switch (integerExpression) {
    case CONSTANT_1:
        statements
        break;
    case CONSTANT_2:
        statements
        break;
    default:
        statements
        break;
}

Empat batasan yang ditegakkan C:

  • Ekspresi switch harus bertipe integer: int, char, short, long, atau enum. Bukan float, bukan double, dan bukan string.
  • Setiap label case harus berupa ekspresi konstanta yang diketahui saat kompilasi. case n: dengan n sebuah variabel adalah error; case 3 + 4: dan case MAX: (konstanta #define atau enum) tidak masalah.
  • Tidak boleh ada dua case dengan nilai yang sama. Duplikat menjadi error kompilasi, dan ini jaring pengaman yang kecil tetapi nyata.
  • Sebuah case tidak bisa menyatakan rentang. case 1 ... 5: adalah ekstensi GCC, bukan C standar; pakai if untuk rentang.

default bersifat opsional dan boleh muncul di mana saja dalam blok, walaupun menaruhnya di akhir adalah konvensi yang hampir universal. Tanpa default, nilai yang tidak cocok akan melewati seluruh switch.

break: Kenapa Tidak Opsional

Hal paling mengejutkan tentang switch di C adalah label case merupakan target lompatan, bukan kotak. Begitu eksekusi mendarat di sebuah label, eksekusi terus berjalan melewati setiap pernyataan di bawahnya, melintasi label case lain, sampai bertemu break atau kurung kurawal penutup.

Switch pertama mencetak one, two, dan three: switch itu cocok dengan case 1 lalu menjalankan semua yang ada sesudahnya. Switch kedua hanya mencetak one. Perilaku itu disebut fall-through, dan lupa menulis break adalah bug switch C yang klasik: programnya diam-diam salah, bukan gagal di-compile.

Compile dengan gcc -Wall -Wextra -Wimplicit-fallthrough dan compiler akan menunjuk setiap case yang jatuh ke case berikutnya.

break pada case terakhir secara teknis berlebihan, karena bloknya memang berakhir di sana. Tetap tulis, supaya ketika nanti ada case baru yang ditambahkan di bawahnya, tidak muncul fall-through secara diam-diam.

Fall-Through yang Disengaja

Fall-through menjadi fitur jika memang disengaja. Menumpuk label tanpa pernyataan di antaranya adalah cara biasa untuk mengatakan "nilai-nilai ini melakukan hal yang sama":

Tiga label berbagi satu badan, tanpa kode yang diduplikasi dan tanpa kondisi || yang panjang. Compiler tidak memberi peringatan untuk bentuk ini, karena tidak ada pernyataan yang dilewati.

Fall-through dengan pernyataan di antaranya, di mana case 1 dijalankan lalu sengaja berlanjut ke case 2, lebih jarang dan layak diberi komentar eksplisit, karena pembaca perlu diberi tahu bahwa break yang hilang itu adalah keputusan:

switch (level) {
    case 3:
        printf("verbose\n");
        /* fall through */
    case 2:
        printf("info\n");
        /* fall through */
    case 1:
        printf("errors\n");
        break;
}

/* fall through */ adalah komentar yang dikenali peringatan GCC, jadi komentar itu juga membungkam pesan diagnostiknya.

Switch pada Karakter

Karena char adalah tipe integer, klasifikasi karakter sangat cocok untuk switch:

Perhatikan bahwa case 'a': memakai tanda kutip tunggal: sebuah konstanta karakter, yang sebenarnya hanyalah nilai integer dari karakter itu. case "a": adalah string dan tidak akan bisa di-compile.

Switch pada Enum

Pasangan terbaik di C adalah switch dengan enum. Label case menjadi nama yang mudah dibaca, dan compiler bisa memberi peringatan jika switch tidak menangani setiap enumerator:

Ada dua hal yang layak ditiru di sini. Setiap case melakukan return, jadi tidak perlu break: return keluar dari fungsi sepenuhnya, dan itu juga mengakhiri switch. Selain itu, tidak ada default: dengan -Wswitch (sudah termasuk di -Wall), tidak menulis default membuat compiler memberi peringatan pada hari seseorang menambahkan state kelima dan lupa memperbarui fungsi ini. default justru akan menyembunyikan masalah itu.

Mendeklarasikan Variabel di Dalam switch

Badan switch adalah satu blok, jadi deklarasi di satu case terlihat di case-case sesudahnya, walaupun belum tentu sudah diinisialisasi. Melompati sebuah inisialisasi adalah error di C:

switch (n) {
    case 1:
        int x = 10;        // error in C: a label cannot precede a declaration this way
        printf("%d\n", x);
        break;
    case 2:
        printf("%d\n", x); // x exists here, but was never initialised
        break;
}

Bungkus case-nya dengan kurung kurawal sendiri jika butuh variabel lokal:

switch (n) {
    case 1: {
        int x = 10;
        printf("%d\n", x);
        break;
    }
    case 2:
        printf("two\n");
        break;
}

switch atau if-else?

Pakai switch jika semua ini terpenuhi: kamu menguji satu ekspresi, ekspresinya bertipe integer, dan kamu membandingkannya dengan konstanta tetap. Penanganan menu, state machine dengan enum, klasifikasi karakter, dan pengiriman perintah adalah contoh klasiknya. Keuntungannya adalah keterbacaan, pengecekan nilai duplikat, dan compiler yang bisa memberi peringatan soal enumerator yang tidak ditangani.

Pakai if-else jika pengujiannya melibatkan rentang (score >= 90), nilai floating-point, string (kamu butuh strcmp), beberapa variabel berbeda, atau kondisi yang digabung dengan && dan ||. Tidak satu pun dari itu bisa dinyatakan sebagai label case.

Performa jarang menjadi penentu. Compiler mengubah switch yang padat menjadi jump table dan switch yang jarang menjadi rangkaian perbandingan, jadi untuk beberapa case saja kedua bentuk itu tidak bisa dibedakan. Pilih yang paling jelas menyatakan maksudmu.

Pertanyaan yang sering diajukan

Bagaimana cara kerja pernyataan switch di C?

switch (expr) mengevaluasi sebuah ekspresi integer satu kali, melompat ke label case yang konstantanya cocok, lalu berjalan dari sana sampai bertemu break atau akhir switch. Jika tidak ada yang cocok, program melompat ke default jika ada, dan jika tidak ada, seluruh bloknya dilewati.

Kenapa saya butuh break di switch C?

Karena label case adalah target lompatan, bukan blok yang terpisah. Tanpa break, eksekusi terus berlanjut ke pernyataan milik case berikutnya. Ini disebut fall-through. break yang terlupa adalah bug switch paling umum di C, dan gcc -Wimplicit-fallthrough akan menandainya.

Bisakah switch dipakai untuk string di C?

Tidak. switch di C butuh ekspresi integer, jadi nilai int, char, dan enum bisa, tetapi string, float, dan rentang tidak. Untuk percabangan berdasarkan string, pakai strcmp dalam rantai if-else, atau petakan dulu string-nya ke enum lalu lakukan switch pada enum itu.

Kapan sebaiknya memakai switch daripada if-else di C?

Pakai switch jika kamu membandingkan satu integer atau karakter dengan daftar konstanta tetap: perintah menu, state enum, klasifikasi karakter. Pakai rantai if-else jika pengujiannya melibatkan rentang, beberapa variabel, atau apa pun selain kesamaan dengan konstanta yang diketahui saat kompilasi.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai