Melalui kesalahan ketik kecil, saya tidak sengaja menemukan konstruk ini:
int main(void) {
char foo = 'c';
switch(foo)
{
printf("Cant Touch This\n"); // This line is Unreachable
case 'a': printf("A\n"); break;
case 'b': printf("B\n"); break;
case 'c': printf("C\n"); break;
case 'd': printf("D\n"); break;
}
return 0;
}
Tampaknya pernyataan printf
di bagian atas switch
itu valid, tetapi juga sama sekali tidak terjangkau.
Saya mendapat kompilasi bersih, bahkan tanpa peringatan tentang kode yang tidak dapat dijangkau, tetapi ini sepertinya tidak ada gunanya.
Haruskah kompiler menandai ini sebagai kode yang tidak terjangkau?
Apakah ini ada gunanya sama sekali?
-Wswitch-unreachable
goto
masuk dan keluar dari bagian yang tidak terjangkau, yang mungkin berguna untuk berbagai peretasan.switch
ini hanya sebuah kondisionalgoto
dengan banyak label. Ada batasan yang kurang lebih sama pada tubuh itu seperti yang Anda miliki pada blok kode reguler yang diisi dengan label goto.Jawaban:
Mungkin bukan yang paling berguna, tetapi tidak sepenuhnya tidak berharga. Anda dapat menggunakannya untuk mendeklarasikan variabel lokal yang tersedia dalam
switch
ruang lingkup.Standar (
N1579 6.8.4.2/7
) memiliki sampel berikut:PS BTW, sampel tidak valid kode C ++. Dalam hal itu (
N4140 6.7/3
, tekankan tambang):Jadi mengganti
int i = 4;
denganint i;
membuatnya menjadi C ++ yang valid.sumber
i
diinisialisasi ke 4, apa yang saya lewatkan?static
, itu akan diinisialisasi ke nol, jadi ada penggunaan yang aman untuk ini juga.i = 4;
inisialisasi, jadi itu tidak pernah terjadi.case
, dan selalu harus menggunakan nama yang berbeda di masingcase
- masing atau mendefinisikannya di luar saklar.Iya. Jika alih-alih pernyataan, Anda meletakkan deklarasi di depan label pertama, ini bisa masuk akal:
Aturan untuk deklarasi dan pernyataan dibagikan untuk blok secara umum, jadi aturan yang sama yang memungkinkan hal itu juga memungkinkan pernyataan di sana.
Layak disebutkan juga bahwa jika pernyataan pertama adalah konstruk loop, label kasus mungkin muncul di tubuh loop:
Tolong jangan menulis kode seperti ini jika ada cara yang lebih mudah dibaca untuk menulisnya, tetapi itu benar-benar valid, dan
f()
panggilan itu dapat dijangkau.sumber
{ /*code*/ switch(x) { } }
mungkin terlihat lebih bersih tetapi juga salah .Ada penggunaan yang terkenal dari Perangkat Duff ini .
Di sini kita menyalin buffer yang ditunjuk oleh
from
ke buffer yang ditunjuk olehto
. Kami menyalincount
contoh data.Itu
do{}while()
pernyataan dimulai sebelum pertamacase
label, dancase
label yang tertanam dalamdo{}while()
.Ini mengurangi jumlah cabang kondisional pada akhir
do{}while()
loop yang ditemui oleh kira-kira faktor 4 (dalam contoh ini; konstanta dapat diubah dengan nilai apa pun yang Anda inginkan).Sekarang, pengoptimal kadang-kadang dapat melakukan ini untuk Anda (terutama jika mereka mengoptimalkan streaming / petunjuk vektor), tetapi tanpa optimasi profil dipandu mereka tidak bisa tahu apakah Anda mengharapkan loop menjadi besar atau tidak.
Secara umum, deklarasi variabel dapat terjadi di sana dan digunakan dalam setiap kasus, tetapi berada di luar ruang lingkup setelah sakelar berakhir. (perhatikan inisialisasi apa pun akan dilewati)
Selain itu, aliran kontrol yang tidak spesifik sakelar dapat membawa Anda ke bagian blok sakelar tersebut, seperti yang diilustrasikan di atas, atau dengan a
goto
.sumber
do {
dancase 0:
tidak masalah, keduanya berfungsi untuk menempatkan target melompat pada yang pertama*to = *from++;
.do {
lebih mudah dibaca. Ya, berdebat tentang keterbacaan untuk Perangkat Duff adalah bodoh dan tidak ada gunanya dan sepertinya cara mudah untuk menjadi gila.Dengan asumsi Anda menggunakan gcc di Linux, itu akan memberi Anda peringatan jika Anda menggunakan versi 4.4 atau yang lebih lama.
Opsi -Wunreachable-code telah dihapus di gcc 4.4 dan seterusnya.
sumber
Tidak hanya untuk deklarasi variabel tetapi juga melompat lanjutan. Anda dapat menggunakannya dengan baik jika dan hanya jika Anda tidak rentan terhadap kode spageti.
Cetakan
Perlu dicatat bahwa switch-case adalah salah satu klausa aliran kontrol tercepat. Jadi pasti sangat fleksibel untuk programmer, yang terkadang melibatkan kasus seperti ini.
sumber
nocase:
dandefault:
?i=4
tidak terpicunocase
.Perlu dicatat, bahwa hampir tidak ada batasan struktural pada kode dalam
switch
pernyataan, atau di manacase *:
label ditempatkan dalam kode ini *. Ini membuat trik pemrograman seperti perangkat duff menjadi mungkin, salah satu implementasi yang mungkin terlihat seperti ini:Anda lihat, kode antara
switch(n%8) {
dancase 7:
label pasti dapat dijangkau ...* Sebagai supercat untungnya ditunjukkan dalam komentar : Sejak C99, baik
goto
label maupun tidak (baik itucase *:
label atau tidak) dapat muncul dalam lingkup deklarasi yang berisi deklarasi VLA. Jadi tidak benar untuk mengatakan bahwa tidak ada batasan struktural pada penempatancase *:
label. Namun, perangkat Duff lebih dulu daripada standar C99, dan itu tidak bergantung pada VLA. Namun demikian, saya merasa harus memasukkan "hampir" ke dalam kalimat pertama saya karena ini.sumber
goto
maupun tidakswitch/case/default
dapat muncul dalam lingkup objek atau tipe yang dinyatakan berbeda-beda. Ini secara efektif berarti bahwa jika suatu blok memuat deklarasi objek atau tipe array panjang variabel, label apa pun harus mendahului deklarasi tersebut. Ada sedikit verbiage yang membingungkan dalam Standar yang akan menyarankan bahwa dalam beberapa kasus cakupan deklarasi VLA meluas ke keseluruhan pernyataan switch; lihat stackoverflow.com/questions/41752072/… untuk pertanyaan saya tentang itu.Anda mendapat jawaban terkait dengan opsi yang diperlukan
gcc
-Wswitch-unreachable
untuk menghasilkan peringatan, jawaban ini adalah untuk menguraikan kegunaan / kelayakan .Mengutip langsung dari
C11
, bab §6.8.4.2, ( penekanan pada saya )Yang sangat jelas. Anda bisa menggunakan ini untuk mendefinisikan variabel
switch
cakupan lokal yang hanya tersedia dalam lingkup pernyataan.sumber
Dimungkinkan untuk mengimplementasikan "loop setengah" dengan itu, meskipun itu mungkin bukan cara terbaik untuk melakukannya:
sumber