Apa tujuan dari blok 'jika (0)' di blok if-else?

141

Pertanyaan saya adalah tentang baris yang saya sebutkan dalam subjek dan yang dapat saya lihat di banyak tempat di dalam kode produksi.

Kode keseluruhan terlihat seperti ini:

if (0) {
    // Empty braces
} else if (some_fn_call()) {
    // actual code
} else if (some_other_fn_call()) {
    // another actual code
    ...
} else {
    // default case
}

Cabang-cabang lain tidak relevan dengan pertanyaan saya. Saya bertanya-tanya apa arti dari menempatkan di if (0)sini. Kawat gigi itu kosong, jadi saya tidak berpikir itu seharusnya mengomentari beberapa blok kode. Apakah itu memaksa kompiler untuk membuat beberapa optimasi atau niatnya berbeda?

Saya telah mencoba mencari kasus eksplisit ini di sini di SO dan di internet, tetapi tidak berhasil. Ada pertanyaan serupa tentang JavaScript, tetapi tidak C. Ada pertanyaan lain, Apa yang terjadi ketika nol ditetapkan dalam kondisi `jika`? , tetapi membahas nol assignment ke variabel, bukan penggunaan 'if (0)' itu sendiri.

Zzaponka
sumber
2
Pernyataan itu sepertinya tidak relevan. Hasilkan kode rakitan dengan dan tanpa pernyataan itu dan Anda akan melihat apa yang terjadi di bawah tenda.
pukul
2
Mungkin saja ini adalah kode yang dibuat secara otomatis.
Aneh

Jawaban:

91

Saya kadang-kadang menggunakan ini untuk simetri sehingga saya bisa bergerak else if{bebas dengan editor saya tanpa harus memikirkan yang pertama if.

Secara semantik

if (0) {
    // Empty braces
} else 

bagian tidak melakukan apa-apa dan Anda dapat mengandalkan pengoptimal untuk menghapusnya.

PSkocik
sumber
239
Pendapat pribadi: Meskipun ini mungkin menjadi kode alasan mengapa ditulis seperti itu, saya pikir itu adalah pembenaran yang buruk. Kode dibaca lebih sering daripada yang tertulis, dan kode yang tidak perlu ini hanya meningkatkan biaya overhead untuk pembaca.
user694733
13
@ user694733: Anda bisa berargumen bahwa if elseawalan umum untuk semua jalur kode signifikan melapisi kondisi dengan baik dan membuatnya lebih mudah untuk memindai. (Namun, itu subjektif, dan akan sangat tergantung pada apa yang sebenarnya ada di dalam kondisi dan blok kode.)
M Oehm
72
Saya tidak berpikir if (0) {..}memperkenalkan masalah keterbacaan / keterbacaan. Itu harus jelas bagi siapa saja yang tahu sedikit C. Itu bukan masalah. Masalahnya adalah pertanyaan lanjutan setelah membacanya: "Untuk apa itu?" Kecuali itu untuk keperluan debugging / sementara (yaitu, tujuannya adalah untuk "mengaktifkan" ifblok itu nanti), saya akan menyarankan untuk menghapus semuanya. Pada dasarnya "membaca" kode seperti itu kemungkinan akan menyebabkan "jeda" yang tidak perlu bagi pembaca tanpa alasan yang jelas. Dan itu alasan yang cukup bagus untuk menghapusnya.
PP
77
Sepertinya itu pasti mengurangi keterbacaan. Itu sangat buruk sehingga mengirim programmer ke SO untuk bertanya untuk apa itu. Bukan pertanda baik.
Vectorjohn
26
Bahkan dengan menggunakan pola ini, saya tidak tahu apakah Anda dapat "bergerak di else ifsekitar editor tanpa khawatir" karena kondisinya mungkin tidak saling eksklusif, dalam hal urutan pesanan penting. Secara pribadi saya hanya akan menggunakan if, dan melakukan pengembalian awal , mengekstraksi rantai logika ke fungsi terpisah jika perlu.
John Wu
105

Ini bisa bermanfaat jika ada #ifpernyataan, ala

   if (0)
   {
       // Empty block
   }
#if TEST1_ENABLED
   else if (test1())
   {
      action1();
   }
#endif
#if TEST2_ENABLED
   else if (test2())
   {
      action2();
   }
#endif

dll.

Dalam hal ini, semua (dan semua) tes dapat #ifdihapus, dan kode akan dikompilasi dengan benar. Hampir semua kompiler akan menghapus if (0) {}bagian tersebut. Autogenerator sederhana dapat menghasilkan kode seperti ini, karena sedikit lebih mudah untuk dikodekan - tidak harus mempertimbangkan blok pertama yang diaktifkan secara terpisah.

CSM
sumber
5
Dalam banyak kasus, rantai if/ else iftidak digunakan sebagai pohon keputusan, melainkan sebagai konstruksi "bertindak atas kondisi pencocokan pertama", di mana kondisi yang kebetulan memiliki prioritas tertinggi tidak terlalu "istimewa". Meskipun saya belum pernah melihat if(0)digunakan sebagai cara untuk memungkinkan semua cabang nyata untuk memiliki sintaks yang konsisten, saya suka sintaks yang konsisten itu memfasilitasi.
supercat
1
Ini bahkan tidak berguna dalam kasus ini karena Anda dapat mencapai efek yang sama tanpa: hanya membagi else ifgaris menjadi dua dan menempatkan penjaga preprocessor di antaranya.
Konrad Rudolph
1
@KonradRudolph Saya tidak mengikuti; bagaimana Anda akan menulisnya?
JiK
1
@JiK saya akan menghapus if (0)cabang dan memformat sisanya sehingga elsepada jalurnya sendiri, dikelilingi oleh penjaga sepanjang garis #if TEST1_ENABLED && TEST2_ENABLED.
Konrad Rudolph
5
@KonradRudolph tidak apa-apa jika Anda ingin menggandakan jumlah penjaga dan tiga kali lipat jumlah kondisi penjaga yang disebutkan, saya kira.
hobbs
44

Saya telah melihat pola serupa yang digunakan dalam kode yang dihasilkan. Sebagai contoh, dalam SQL, saya telah melihat perpustakaan mengeluarkan whereklausa berikut .

where 1 = 1

Hal ini mungkin membuatnya lebih mudah untuk hanya menambahkan kriteria lain, karena semua kriteria tambahan dapat ditambahkan dengan andbukannya memeriksa tambahan untuk melihat apakah itu adalah kriteria pertama atau tidak.

Seth Flowers
sumber
4
Ini 1=1juga "berguna" karena Anda selalu dapat menambahkan wheredi depan, tanpa syarat. Kalau tidak, Anda harus memeriksa apakah itu kosong, dan jika demikian hindari menghasilkan whereklausa.
Bakuriu
2
Selain itu, sebagian besar basis data akan secara otomatis "menghapus" 1=1dari WHERE, sehingga tidak berdampak pada kinerja.
Dana Gugatan Monica
7
Ini dapat diterima di perpustakaan yang secara otomatis menghasilkan kueri SQL yang kemungkinan besar tidak pernah dilihat bahkan oleh tim DevOps. Itu tidak "dapat diterima" dalam kode tingkat tinggi yang harus ditulis dan dibaca berulang kali.
phagio
Ini adalah pendekatan yang sangat berguna ketika menghasilkan beberapa jenis SQL dinamis dengan jumlah kondisi final yang tidak diketahui.
Kapten
1
@ aneh memang saya menulis sebaliknya: sintaks yang buruk dibaca diterima dalam kode yang dihasilkan karena kemungkinan besar tidak akan pernah dibaca, tidak dalam kode fungsional tingkat tinggi yang dikelola oleh pengembang.
phagio
44

Seperti yang tertulis, if (0) {}klausa tidak bisa dikompilasi.

Saya menduga fungsi klausa di bagian atas tangga ini adalah untuk menyediakan tempat yang mudah untuk menonaktifkan sementara semua fungsi lainnya sekaligus (untuk tujuan debugging atau perbandingan) dengan mengubah 0ke 1atau true.

Russell Borogove
sumber
2
Berhasil. Saya tidak bisa melihat alasan lain selain debugging.
tfont
16

Saya tidak yakin dengan optimasi apa pun, tetapi dua sen saya:

Ini terjadi karena beberapa modifikasi kode, di mana satu kondisi utama telah dihapus, (fungsi memanggil di ifblok awal , katakanlah), tetapi pengembang / pengelola

jadi alih-alih menghapus ifblok terkait , mereka hanya mengubah kondisi if(0)dan pindah.

Sourav Ghosh
sumber
3
Bukankah if(0)mengurangi cakupan cabang juga?
David Szalai
1
@ Davidvidszalai Tidak sepenuhnya - paling banyak itu akan berkurang 1 (dari 2 sebelumnya) - tetapi satu hit masih akan diperlukan untuk cakupan, sejauh yang saya tahu.
Sourav Ghosh
15

Ini membusuk kode.

Pada titik tertentu bahwa "jika" melakukan sesuatu yang bermanfaat, situasinya berubah, mungkin variabel yang dievaluasi dihapus.

Orang yang memperbaiki / mengubah sistem melakukan sesedikit mungkin untuk mempengaruhi logika sistem sehingga ia hanya memastikan kode akan dikompilasi ulang. Jadi dia meninggalkan "jika (0)" karena itu cepat dan mudah dan dia tidak sepenuhnya yakin itu yang ingin dia lakukan. Dia membuat sistem bekerja dan dia tidak kembali untuk memperbaikinya sepenuhnya.

Kemudian pengembang berikutnya datang dan berpikir bahwa itu dilakukan dengan sengaja dan hanya berkomentar bahwa bagian dari kode (karena itu tidak dievaluasi pula), maka pada saat kode disentuh komentar-komentar tersebut dihapus.

Materi Gelap
sumber
2
Ya. Untuk kode kuno, buat satu perubahan penghapus kode mati pada satu waktu. Saya tidak dapat menghitung berapa kali saya melakukan slash-and-burn mengamuk terhadap kode "mati" hanya untuk menemukan ada beberapa efek samping aneh yang melukai dan membakar dilewatkan.
Julie di Austin
15

Satu kemungkinan belum disebutkan: if (0) {garis mungkin menyediakan tempat yang nyaman untuk breakpoint.

Debugging sering dilakukan pada kode yang tidak dioptimalkan sehingga tes selalu-salah akan hadir dan dapat memiliki set breakpoint di atasnya. Ketika dikompilasi untuk produksi, garis kode akan dioptimalkan. Baris yang tampaknya tidak berguna memberikan fungsionalitas untuk pengembangan dan pengujian build tanpa memengaruhi build rilis.

Ada saran bagus lainnya di atas juga; satu-satunya cara untuk benar-benar tahu apa tujuannya, adalah melacak penulis dan bertanya. Sistem kontrol kode sumber Anda mungkin bisa membantu. (Cari blamefungsionalitas -type.)

pelajar
sumber
9

Saya telah melihat blok kode yang tidak dapat dijangkau dalam JavaScript yang diperluas yang telah dibuat menggunakan bahasa templating.

Misalnya, kode yang Anda baca bisa saja ditempelkan dari server yang pra-mengevaluasi kondisi pertama yang pada saat itu bergantung pada variabel yang hanya tersedia di sisi server.

if ( ${requestIsNotHttps} ){ ... }else if( ...

yang pernah pra-disusun pagar:

if ( 0 ){ ... }else if ( ...

Saya harap ini membantu Anda merelatifkan potensi aktivitas papan ketik rendah dari zaman coders pro-daur ulang yang membuat saya sangat antusias!

simonarame
sumber
1
Saya setuju, di zaman otomatisasi di mana-mana kita harus lebih mengandalkan kode autogenerasi, karena memungkinkan kita menghabiskan lebih banyak waktu untuk hal-hal yang sebenarnya. Tetapi untuk saat ini, poin saya yang menarik adalah bagaimana semua ini dirancang di bawah tenda.
Zzaponka
8

Konstruk itu juga dapat digunakan dalam C untuk mengimplementasikan pemrograman generik dengan tipe keselamatan, dengan mengandalkan pada fakta bahwa kode yang tidak terjangkau masih diperiksa oleh kompiler:

// this is a generic unsafe function, that will call fun(arg) at a later time
void defer(void *fun, void *arg);

// this is a macro that makes it safer, by checking the argument
// matches the function signature
#define DEFER(f, arg) \
   if(0) f(arg); \              // never actually called, but compile-time checked
   else defer(f, (void *)arg);  // do the unsafe call after safety check

void myfunction(int *p);

DEFER(myfunction, 42);     // compile error
int *b;
DEFER(myfunction, b);      // compiles OK
philfr
sumber
6

Saya pikir itu hanya kode yang buruk. Menulis contoh cepat di Compiler Explorer, kita melihat bahwa di gcc dan dentang tidak ada kode yang dihasilkan untuk if (0)blok, bahkan dengan optimasi sepenuhnya dinonaktifkan:

https://godbolt.org/z/PETIks

Bermain-main dengan menghapus if (0)penyebab tidak ada perubahan pada kode yang dihasilkan, jadi saya menyimpulkan bahwa ini bukan optimasi.

Mungkin saja ada sesuatu di ifblok atas yang kemudian dihapus. Singkatnya, sepertinya menghapusnya akan menyebabkan kode yang sama persis dihasilkan, jadi jangan ragu untuk melakukannya.

situs cha0
sumber
6

Seperti yang telah dikatakan, nol dievaluasi menjadi false, dan cabang kemungkinan akan dioptimalkan oleh kompiler.

Saya juga pernah melihat ini sebelumnya dalam kode di mana fitur baru ditambahkan dan kill-switch diperlukan (jika ada yang salah dengan fitur Anda hanya dapat mematikannya), dan beberapa waktu kemudian ketika kill-switch dihapus programmer juga tidak menghapus cabang, misalnya

if (feature_a_active()) {
    use_feature_a();
} else if (some_fn()) {
   ...

menjadi

if (0) {
   // empty
} else if (some_fn()) {
   ...
sergiopm
sumber
1

Ini membantu untuk men-debug blok ini hanya dengan meletakkan jika blok 1. Ini menonaktifkan semua fungsi blok jika lain Dan juga kita dapat memperluas blok if else.

Abdul Ahad Sheikh
sumber
1
    Actually according to my opinion, if we put any variable for checking inside
    e.g:-
public static void main(string args[])
{
        var status;
        var empList=_unitofWork.EmpRepository.Get(con=>con.isRetired==true);
        //some code logic 
        if(empList.count>0)
        {
          status=true;
        }
        if(status)
        {
         //do something
        }
        else
        {
        //do something else
        }
}
     if then its dynamically get the value in run time and invoke the logic inside it, else its simply extra line of code i guess.

    Anybody have any depth knowledge why this thing is used....or agree with me.
    kindly respond. 
Sagar Kumar Choudhury
sumber
1

@ Jawaban PSkocik baik-baik saja, tapi saya menambahkan dua sen saya. Tidak yakin apakah saya harus melakukan ini sebagai komentar, atau sebagai jawaban; memilih yang terakhir, karena IMHO layak dilihat orang lain, sedangkan komentar sering tidak terlihat.

Saya tidak hanya sesekali menggunakan

if(0) {
   //deliberately left empty
} else if( cond1 ) {
   //deliberately left empty
} else if( cond2 ) {
   //deliberately left empty
...
} else {
   // no conditions matched
}

Tapi saya juga sesekali melakukannya

if( 1 
    && cond1 
    && cond2
    ...
    && condN
) {

atau

if( 0 
    || cond1 
    || cond2
    ...
    || condN
) {

untuk kondisi yang rumit. Untuk alasan yang sama - lebih mudah untuk diedit, #ifdef, dll.

Untuk itu, di Perl saya akan lakukan

@array = (  
    elem1,
    elem2,
    ...
    elem1,
) {
  • catat koma di akhir daftar. Saya lupa jika koma adalah pemisah atau pembatas dalam daftar C dan C ++. IMHO, ini adalah satu hal yang telah kami pelajari: [ Apakah membuntuti koma di Perl adalah praktik yang buruk? koma] adalah hal yang baik. Seperti halnya notasi baru, perlu waktu untuk terbiasa.

Saya membandingkan if(0)kode dengan lisp

(cond   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn))

yang, Anda dapat menebaknya, saya mungkin indent sebagai

(cond   
   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn)
)

Saya kadang-kadang mencoba membayangkan seperti apa sintaksis yang bisa dibaca manusia untuk ini.

Mungkin

IF
:: cond1 THEN code1
:: cond2 THEN code2
...
:: condN THEN codeN
FI

terinspirasi oleh Dikstra [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if[[Guarded Command Language].

Tetapi sintaks ini menyiratkan bahwa kondisi dievaluasi secara paralel, sedangkan if...else-ifmenyiratkan evaluasi kondisi berurutan dan diprioritaskan.

Saya mulai melakukan hal semacam ini ketika menulis program yang menghasilkan program lain, di mana itu sangat nyaman.

Sementara kita berada di dalamnya, ketika menulis RTL menggunakan iHDL lama Intel, saya memiliki hal-hal seperti kode

   IF 0 THEN /*nothing*/
   **FORC i FROM 1 TO 10 DOC** 
   ELSE IF signal%i% THEN    
      // stuff to do if signal%i% is active
   **ENDC** 
   ELSE   
      // nothing matched 
   ENDIF

di mana FORC..DOC..ENDCadalah konstruksi lingkaran preprocessor makro, yang diperluas ke

   IF 0 THEN /*nothing*/
   ELSE IF signal1 THEN    
      // stuff to do if signal1 is active
   ELSE IF signal2 THEN    
      // stuff to do if signal2 is active
   ...
   ELSE IF signal100 THEN    
      // stuff to do if signal100 is active
   ELSE   
      // nothing matched 
   ENDIF

Ini adalah penugasan tunggal, non-imperatif, kode, jadi menetapkan variabel keadaan tidak diizinkan, jika Anda perlu melakukan hal-hal seperti menemukan bit set pertama.

   IF 0 THEN /*nothing*/
   ELSE IF signal1 THEN    
      found := 1
   ELSE IF signal2 THEN    
      found := 2
   ...
   ELSE IF signal100 THEN    
      found := 100
   ELSE   
      // nothing matched 
   ENDIF

Kalau dipikir-pikir, ini mungkin adalah tempat pertama yang saya temui konstruksi seperti itu.

BTW, keberatan bahwa sebagian orang memiliki gaya if (0) - bahwa kondisi lain-jika-tergantung secara berurutan dan tidak dapat secara sewenang-wenang dipesan ulang - tidak berlaku untuk logika AND dan OR dan XOR dalam RTL - tetapi berlaku untuk short- sirkuit && dan ||.

Krazy Glew
sumber
-1

Saya telah melihat ini digunakan untuk menangani kesalahan, misalnya

if(0){
lable1:
   //do something
}
if(0){
lable2:
   //do something
}
.
.
and so on.

if(condition_fails)
   goto lable1;

Ini bisa membantu ketika goto digunakan untuk mengelola kesalahan, pernyataan dieksekusi hanya ketika kesalahan terjadi. Saya melihat ini dalam kode C yang sangat lama (di mana argumen fungsi ditulis di luar '()'), jangan berpikir ada yang mengikuti ini sekarang.

Jayachandra M
sumber
-2

Saya telah melihat ini beberapa kali, saya pikir alasan yang paling mungkin adalah ia mengevaluasi sesuatu dalam versi / cabang / kode yang berbeda, atau mungkin untuk debugging, dan mengubahnya menjadi if(0)cara yang agak malas untuk menghapus apa pun yang ada di sana .

John U
sumber