Pertimbangkan switch
pernyataan berikut :
switch( value )
{
case 1:
return 1;
default:
value++;
// fall-through
case 2:
return value * 2;
}
Kode ini mengkompilasi, tetapi apakah ini valid (= perilaku yang ditentukan) untuk C90 / C99? Saya belum pernah melihat kode di mana kasus default bukan kasus terakhir.
EDIT:
Seperti yang ditulis Jon Cage dan KillianDS : ini adalah kode yang sangat jelek dan membingungkan dan saya sangat menyadarinya. Saya hanya tertarik pada sintaks umum (apakah didefinisikan?) Dan output yang diharapkan.
c
switch-statement
tanascius
sumber
sumber
goto
tidak jahat. Pengikut kultus kargo adalah! Anda tidak dapat membayangkan sampai sejauh mana orang-orang ekstrem dapat menghindarinyagoto
karena itu sangat jahat, membuat kode mereka berantakan.goto
terutama untuk mensimulasikan sesuatu sepertifinally
klausa dalam fungsi, di mana sumber daya (file, memori) harus dirilis ketika berhenti, dan mengulangi untuk setiap kasus kesalahan daftarfree
danclose
tidak membantu keterbacaan. Meskipun ada satu penggunaangoto
yang ingin saya hindari tetapi tidak bisa, adalah ketika saya ingin keluar dari lingkaran dan saya berada diswitch
dalam lingkaran itu.Jawaban:
Standar C99 tidak eksplisit tentang hal ini, tetapi jika menggabungkan semua fakta, ini benar-benar valid.
A
case
dandefault
label sama dengangoto
label. Lihat 6.8.1 Pernyataan berlabel. Yang sangat menarik adalah 6.8.1.4, yang memungkinkan Perangkat Duff yang telah disebutkan:Sunting : Kode dalam sakelar tidak ada yang istimewa; ini adalah blok kode normal seperti pada-
if
pernyataan, dengan label lompatan tambahan. Ini menjelaskan perilaku jatuh dan mengapabreak
perlu.6.8.4.2.7 bahkan memberikan contoh:
Konstanta kasing harus unik dalam pernyataan sakelar:
Semua kasus dievaluasi, kemudian melompat ke label default, jika diberikan:
sumber
default
kasus yang mendominasi kasus-kasus lain sekitar 100: 1, dan saya tidak tahu apakahdefault
kasusnya valid atau tidak ditentukan untuk membuat kasus pertama.Pernyataan kasus dan pernyataan default dapat terjadi dalam urutan apa pun dalam pernyataan switch. Klausa default adalah klausa opsional yang cocok jika tidak ada konstanta dalam pernyataan kasus dapat dicocokkan.
Contoh yang baik :-
sangat berguna jika Anda ingin kasus Anda disajikan dalam urutan logis dalam kode (seperti pada, tidak mengatakan kasus 1, kasus 3, kasus 2 / default) dan kasus Anda sangat panjang sehingga Anda tidak ingin mengulangi seluruh kasus kode di bagian bawah untuk default
sumber
Ini valid dan sangat berguna dalam beberapa kasus.
Pertimbangkan kode berikut:
Intinya adalah bahwa kode di atas lebih mudah dibaca dan efisien daripada mengalir
if
. Anda bisa meletakkannyadefault
di akhir, tetapi tidak ada gunanya karena akan memusatkan perhatian Anda pada kasus kesalahan daripada kasus normal (yang di sini adalahdefault
kasus).Sebenarnya, itu bukan contoh yang baik, karena
poll
Anda tahu berapa banyak peristiwa yang paling banyak terjadi. Titik nyata saya adalah bahwa ada yang kasus dengan satu set didefinisikan dari nilai input di mana ada 'pengecualian' dan kasus normal. Jika lebih baik menempatkan pengecualian atau kasus normal di depan adalah masalah pilihan.Dalam bidang perangkat lunak saya memikirkan kasus yang sangat umum: rekursi dengan beberapa nilai terminal. Jika Anda dapat mengekspresikannya menggunakan sakelar,
default
akan menjadi nilai biasa yang berisi panggilan rekursif dan elemen yang dibedakan (masing-masing kasing) nilai terminal. Biasanya tidak perlu fokus pada nilai terminal.Alasan lain adalah bahwa urutan kasus dapat mengubah perilaku kode yang dikompilasi, dan itu penting untuk kinerja. Sebagian besar kompiler akan menghasilkan kode rakitan yang dikompilasi dalam urutan yang sama dengan kode yang muncul di sakelar. Itu membuat case pertama sangat berbeda dari yang lain: semua case kecuali yang pertama akan melibatkan lompatan dan yang akan mengosongkan jalur pipa prosesor. Anda mungkin memahaminya seperti prediktor cabang default untuk menjalankan kasing pertama yang muncul di sakelar. Jika suatu kasus jika jauh lebih umum daripada yang lain maka Anda memiliki alasan yang sangat baik untuk menjadikannya sebagai kasus pertama.
Membaca komentar adalah alasan spesifik mengapa poster asli mengajukan pertanyaan itu setelah membaca reorganisasi Intel Loop Cabang kompilasi tentang optimasi kode.
Maka akan menjadi beberapa arbitrase antara keterbacaan kode dan kinerja kode. Mungkin lebih baik untuk memberikan komentar untuk menjelaskan kepada pembaca di masa depan mengapa suatu kasus muncul terlebih dahulu.
sumber
case
. Apa yang menyedihkan adalah bahwa itu terlihat seperti gula sintaksis dan tidak akan merusak kode yang ada jika didukung.ya, ini valid, dan dalam beberapa keadaan bahkan berguna. Secara umum, jika Anda tidak membutuhkannya, jangan lakukan itu.
sumber
Tidak ada urutan yang ditentukan dalam pernyataan switch. Anda dapat melihat kasing sebagai sesuatu seperti label bernama, seperti
goto
label. Bertentangan dengan apa yang tampaknya dipikirkan orang di sini, dalam hal nilai 2 label default tidak melompat ke. Untuk menggambarkan dengan contoh klasik, berikut adalah perangkat Duff , yang merupakan anak poster dari ekstremswitch/case
di C.sumber
Satu skenario di mana saya akan menganggap tepat untuk memiliki 'default' yang terletak di tempat lain selain akhir dari pernyataan kasus adalah di mesin negara di mana keadaan yang tidak valid harus mengatur ulang mesin dan melanjutkan seolah-olah itu adalah keadaan awal. Sebagai contoh:
pengaturan alternatif, jika keadaan tidak valid tidak boleh mereset mesin tetapi harus mudah diidentifikasi sebagai keadaan tidak valid:
Kode di tempat lain kemudian dapat memeriksa (widget_state == WIDGET_INVALID_STATE) dan memberikan perilaku pelaporan kesalahan atau pengaturan ulang negara apa pun yang tampaknya sesuai. Misalnya, kode bilah status dapat menampilkan ikon kesalahan, dan opsi menu "mulai widget" yang dinonaktifkan di sebagian besar negara non-idle dapat diaktifkan untuk WIDGET_INVALID_STATE serta WIDGET_IDLE.
sumber
Menyambung dengan contoh lain: Ini bisa bermanfaat jika "default" adalah kasus yang tidak terduga, dan Anda ingin mencatat kesalahan tetapi juga melakukan sesuatu yang masuk akal. Contoh dari beberapa kode saya sendiri:
sumber
Ada beberapa kasus ketika Anda mengonversi ENUM ke string atau mengubah string menjadi enum jika Anda menulis / membaca ke / dari file.
Terkadang Anda perlu membuat salah satu nilai default untuk menutupi kesalahan yang dibuat dengan mengedit file secara manual.
sumber
The
default
kondisi dapat menjadi suatu tempat dalam switch yang klausul kasus bisa eksis. Tidak perlu menjadi klausa terakhir. Saya telah melihat kode yang menempatkan default sebagai klausa pertama. Thecase 2:
dijalankan secara normal, meskipun klausa default adalah di atas itu.Sebagai tes, saya meletakkan kode sampel dalam suatu fungsi, dipanggil
test(int value){}
dan dijalankan:Outputnya adalah:
sumber
Itu sah, tapi agak jahat. Saya menyarankan itu umumnya buruk untuk membiarkan jatuh karena dapat menyebabkan beberapa kode spaghetti yang sangat berantakan.
Ini hampir pasti lebih baik untuk memecah kasus-kasus ini menjadi beberapa pernyataan switch atau fungsi yang lebih kecil.
[edit] @ Kristopia: Contoh Anda:
akan lebih jelas untuk niat itu (saya pikir) jika itu ditulis seperti ini:
[edit2] @ristopia: Contoh kedua Anda mungkin adalah contoh terbersih dari penggunaan yang baik untuk tindak lanjut:
..tapi secara pribadi saya akan membagi pengakuan komentar menjadi fungsinya sendiri:
sumber
r
adalah array tujuan,wc
adalahwchar_t
saklar input (utf8_length) {/ * Catatan: kode jatuh melalui kasus! * / case 3: r [2] = 0x80 | (wc & 0x3f); wc >> = 6; wc | = 0x800; case 2: r [1] = 0x80 | (wc & 0x3f); wc >> = 6; wc | = 0xc0; case 1: r [0] = wc; }for(i=0; s[i]; i++) { switch(s[i]) { case '"': case '\'': case '\\': d[dlen++] = '\\'; /* fall through */ default: d[dlen++] = s[i]; } }