İf-else bloğundaki 'if (0)' bloğunun amacı nedir?


141

Sorum, konuya değindiğim ve üretim kodunun içinde birçok yerde görebildiğim çizgiyle ilgili.

Genel kod şöyle görünür:

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

Diğer şubeler sorumla ilgisiz. Buraya koymanın anlamının ne olduğunu merak ediyorum if (0). Parantez boş, bu yüzden bazı kod bloğu yorum gerekiyordu sanmıyorum. Derleyiciyi bir miktar optimizasyon yapmaya zorluyor mu veya niyetleri farklı mı?

Bu açık davayı burada SO'da ve internette aramaya çalıştım, ancak başarılı olamadım. JavaScript ile ilgili benzer sorular var, ancak C değil. Başka bir soru var, `if 'durumunda sıfır atandığında ne olur? , ancak bir değişkene sıfır atamasını tartışır, 'if (0)' kullanımının kendisini değil.


2
Bu ifade ilgisiz görünüyor. Bu ifadeyle veya ifadesiz montaj kodu oluşturun ve başlık altında neler olduğunu göreceksiniz.
9'da haccks

2
Bu otomatik olarak oluşturulan bir kod olabilir.
ucube

Yanıtlar:


91

Bazen simetri için kullanıyorum, böylece else if{ilkini düşünmek zorunda kalmadan editörümle diğerini serbestçe hareket ettirebiliyorumif .

Anlamsal olarak

if (0) {
    // Empty braces
} else 

parçası hiçbir şey yapmaz ve onu silmek için optimize edicilere güvenebilirsiniz.


239
Kişisel görüş: Bu, olduğu gibi yazılmasının neden kodu olsa da, bunun kötü bir gerekçe olduğunu düşünüyorum. Kod yazıldığından daha sık okunur ve bu gereksiz kod sadece okuyucu için ayrıştırma yükünü artırır.
user694733

13
@ user694733: if elseTüm önemli kod yollarının ortak önekinin koşulları iyi hizaladığını ve taramayı kolaylaştırdığını iddia edebilirsiniz. (Ancak bu özneldir ve koşulların ve kod bloklarının içinde gerçekten olan şeylerin
çoğuna

72
if (0) {..}Herhangi bir parsabilite / okunabilirlik problemi getirdiğini düşünmüyorum . C'yi bilen herkes için açık olmalı. Bu bir sorun değil. Sorun, okuduktan sonra takip eden soru: "O zaman ne için?" Hata ayıklama / geçici amaçlar için olmadığı sürece (yani, niyet ifdaha sonra bu bloğu "etkinleştirmek" ), tamamen kaldırmayı savunurdum. Temelde böyle bir kodu "okumak", büyük olasılıkla okuyucu için gereksiz bir "duraklamaya" neden olur. Ve bu onu kaldırmak için yeterince iyi bir neden.
PP

77
Kesinlikle okunabilirlikten uzaklaşıyor gibi görünüyor. O kadar kötüydü ki programcı ne için olduğunu soracaktı. İyi bir işaret değil.
Vectorjohn

26
Bu kalıbı kullanarak bile, " else ifendişe duymadan editörde hareket edip edemeyeceğinizi" bilmiyorum çünkü koşullar birbirini dışlamayabilir, bu durumda sipariş önemlidir. Şahsen ben sadece kullanırım ifve gerekirse erken mantık zincirini ayrı bir fonksiyona çıkararak erken dönüş yaparım .
John Wu

105

Bu #ififadeler varsa yararlı olabilir , ala

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

vb.

Bu durumda, testlerin herhangi biri (ve tümü) #ifdüzenlenebilir ve kod doğru şekilde derlenir. Hemen hemen tüm derleyiciler if (0) {}parçayı kaldıracaktır . Basit bir otomatik jeneratör, kodlamak biraz daha kolay olduğu için böyle bir kod üretebilir - ilk etkin bloğu ayrı ayrı düşünmek zorunda değildir.


5
Çoğu durumda, if/ else ifzinciri bir karar ağacı kadar kullanılmaz, daha ziyade en yüksek önceliğe sahip olan durumun özellikle "özel" olmadığı bir "ilk eşleştirme koşulu üzerine eylem" yapısı olarak kullanılır. if(0)Tüm gerçek dalların tutarlı sözdizimine sahip olmasına izin vermenin bir yolu olarak görülmese de, kolaylaştırdığı tutarlı sözdizimini seviyorum.
supercat

1
Bu durumda bile yararlı değildir, çünkü aynı etkiyi olmadan da elde edebilirsiniz: sadece else ifhattı ikiye ayırın ve önişlemci koruyucusunu araya koyun.
Konrad Rudolph

1
@KonradRudolph Takip etmiyorum; nasıl yazardın
JiK

1
@JiK if (0)Şube kaldırır ve gerisini elsekendi çizgisinde olacak, çizgileri boyunca bir muhafızla çevrelenmiş olacaktım #if TEST1_ENABLED && TEST2_ENABLED.
Konrad Rudolph

5
@KonradRudolph, koruma sayısını iki katına çıkarmak ve bahsi geçen koruma koşullarının sayısını üçe katlamak istiyorsanız, sanırım.
ocaklar

44

Ben oluşturulan kod kullanılan benzer bir desen gördüm. Örneğin, SQL'de kütüphanelerin aşağıdaki wheremaddeyi yaydıklarını gördüm .

where 1 = 1

Bu, muhtemelen diğer ölçütlerin eklenmesini kolaylaştırır, çünkü andilk ölçüt olup olmadığını görmek için ek bir kontrol yerine tüm ek ölçütler eklenebilir .


4
1=1Her zaman ekleyebilir çünkü aynı zamanda "yararlı" olduğunu wherekoşulsuz, ön. Aksi takdirde, boş olup olmadığını kontrol etmeniz gerekir ve eğer öyleyse wheremaddeyi oluşturmaktan kaçının .
Bakuriu

2
Buna ek olarak, çoğu veritabanı otomatik olarak '' kaldırır ' 1=1' WHERE, bu nedenle performans üzerinde bir etkisi yoktur.
Monica'nın Davası

7
Bu, DevOps ekibi tarafından bile hiç görülmeyen SQL sorgularını otomatik olarak üreten bir kitaplıkta kabul edilebilir. Birden çok kez yazılması ve okunması gereken üst düzey kodda "kabul edilebilir" değildir.
phagio

Bu, bilinmeyen sayıda son koşula sahip bir tür dinamik SQL oluştururken gerçekten kullanışlı bir yaklaşımdır .
Kaptan

1
@ freakish gerçekten de tam tersini yazdım: zayıf okunabilir sözdizimi oluşturulan kod kabul edilebilir çünkü büyük olasılıkla asla okunmayacak, geliştiriciler tarafından tutulan yüksek seviyeli fonksiyonel kod.
phagio

44

if (0) {}Yazıldığı gibi, madde hiçbir şeye derlenmez.

Bu merdivenin tepesinde maddesinin işlevi değiştirilerek (ayıklama veya karşılaştırma amaçlı) bir defada geçici olarak devre dışı tüm diğer işlevleri için kolay bir yer sağlamak için şüpheli 0bir etmek 1veya true.


2
Başarmak. Hata ayıklamanın yanı sıra başka bir neden göremedim.
tfont

16

Herhangi bir optimizasyon emin değilim, ama benim iki sent:

Bu, bir birincil koşulun kaldırıldığı bazı kod değişiklikleri nedeniyle oldu (ilk ifbloktaki fonksiyon çağrısı diyelim), ancak geliştiriciler / koruyucular

bu yüzden ilişkili ifbloğu kaldırmak yerine , koşulu basitçe değiştirdiler ve devam ettiler if(0).


3
Is not if(0)çok şube kapsama azaltmak?
David Szalai

1
@DavidSzalai Tamamen değil - en fazla 1 azalır (önceki 2'den) - ancak kapsama alanı için bilgim dahilinde bir vuruş gerekli olacaktır.
Sourav Ghosh

15

Kod çürüklüğü.

Bir noktada "yararlı" bir şey yaptıysa, durum değişti, belki de değerlendirilen değişken kaldırıldı.

Sistemi düzelten / değiştiren kişi, sistemin mantığını etkilemek için mümkün olduğunca az şey yaptı böylece kodun yeniden derlenmesini sağladı. Bu yüzden bir "if (0)" bırakır, çünkü bu hızlı ve kolaydır ve ne yapmak istediğinden tam olarak emin değildir. Sistemi çalıştırıyor ve tamamen düzeltmek için geri dönmüyor.

Daha sonra bir sonraki geliştirici gelir ve bunun kasten yapıldığını düşünür ve sadece kodun bir kısmını yorumlar (yine de değerlendirilmediği için), daha sonra koda bir daha dokunduğunda bu yorumlar kaldırılır.


2
Evet. Eski kodlar için, bir kerede bir ölü kod kaldırma değişikliği yapın. Sadece "ölü" koda karşı eğik çizgi ve yanık patlaması yaptığım sayıları sayamıyorum, sadece eğik çizgi ve yanmanın kaçırdığı garip bir yan etki olduğunu keşfettim.
Julie in Austin

15

Henüz bahsedilmeyen bir olasılık: if (0) {hat bir kesme noktası için uygun bir nokta olabilir.

Hata ayıklama genellikle optimize edilmemiş kodda yapılır, böylece her zaman yanlış test mevcut olur ve üzerinde kesme noktası ayarlanabilir. Üretim için derlendiğinde, kod satırı optimize edilecektir. Görünüşte işe yaramayan çizgi, geliştirme sürümlerini etkilemeden geliştirme ve test yapıları için işlevsellik sağlar.

Yukarıda başka iyi öneriler de var; amacın ne olduğunu gerçekten bilmenin tek yolu yazarı izlemek ve sormaktır. Kaynak kodu kontrol sisteminiz bu konuda yardımcı olabilir. ( blame-Tip işlevselliği arayın .)


9

Önceden genişletilmiş JavaScript'te cazip bir dil kullanılarak oluşturulmuş erişilemeyen kod blokları gördüm.

Örneğin, okuduğunuz kod, o sırada yalnızca sunucu tarafında bulunan bir değişkene dayanan ilk koşulu önceden değerlendiren bir sunucudan yapıştırılmış olabilir.

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

önceden derlenmiş olan

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

Umarım bu, coşkuyu tezahür ettirdiğim geri dönüşüm kodlayıcıları döneminin potansiyel düşük klavye aktivitesini yeniden görmenize yardımcı olur!


1
Her yerde otomasyon çağında, gerçek üretimlere daha fazla zaman harcamamıza izin verdiği için, otomatik olarak oluşturulan koda daha fazla güvenmemiz gerektiğine katılıyorum. Ama şimdilik, benim asıl ilgilendiğim, bunun her şeyin kaputun altında nasıl yapılandırıldığı.
Zzaponka

8

Bu yapı, erişilemeyen kodun derleyici tarafından hala kontrol edildiğine dayanarak, tip güvenliği ile genel programlama uygulamak için C'de de kullanılabilir:

// 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

6

Bence bu sadece kötü bir kod. Derleyici Gezgini'nde hızlı bir örnek yazdığımızda, hem gcc hem de clang'da,if (0) , optimizasyonlar tamamen devre dışı bırakılmış olsa bile blok :

https://godbolt.org/z/PETIks

Kaldırılan oyunların if (0)nedenleri oluşturulan kodda herhangi bir değişikliğe neden olmaz, bu yüzden bunun bir optimizasyon olmadığı sonucuna varıyorum.

Üst ifblokta daha sonra çıkarılan bir şey olması mümkündür . Kısacası, kaldırılması aynı kodun oluşturulmasına neden olacak gibi görünüyor, bu yüzden bunu yapmaktan çekinmeyin.


6

Söylendiği gibi, sıfır yanlış olarak değerlendirilir ve dal muhtemelen derleyici tarafından optimize edilir.

Daha önce yeni bir özelliğin eklendiği ve bir kill-switch'in gerekli olduğu kodda bunu gördüm (bu özellikle ilgili bir sorun olursa sadece kapatabilirsiniz) ve bir süre sonra kill-switch kaldırıldığında programcı da dalı kaldırmadı, ör.

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

oldu

if (0) {
   // empty
} else if (some_fn()) {
   ...

1

Bu blok sadece blok 1 koyarak koyarak hata ayıklamaya yardımcı olur. Ayrıca if bloğunu genişletebiliriz.


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. 

1

@ PSkocik'in cevabı iyi, ama ben iki sent ekliyorum. Bunu bir yorum olarak mı yoksa bir cevap olarak mı yapmam gerektiğinden emin değilim; ikincisini seçmek, çünkü IMHO başkalarına görülmeye değer, oysa yorumlar sıklıkla görünmezdir.

Sadece arada sırada kullanmıyorum

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

Ama ben de arada sırada yaparım

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

veya

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

karmaşık durumlar için. Aynı nedenlerle - daha kolay düzenleme, #ifdef vb.

Bu konuda, Perl'de yapacağım

@array = (  
    elem1,
    elem2,
    ...
    elem1,
) {
  • listenin sonunda virgül kullanın. Virgül C ve C ++ listelerinde ayırıcı veya ayırıcı olup olmadığını unutuyorum. IMHO bu öğrendiğimiz bir şey: [ Perl'de virgül kullanmak kötü bir uygulama mı? virgül] iyi bir şeydir. Herhangi bir yeni gösterim gibi, alışmak biraz zaman alır.

if(0)Kodu lisp ile karşılaştırırım

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

ki, tahmin ettiniz, girintili olarak

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

Bazen bunun için daha insan tarafından okunabilir bir sözdiziminin nasıl olabileceğini hayal etmeye çalıştım.

belki

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

esinlenerek Dikstra'nın [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if 162[Guarded Komut Dili].

Ancak bu sözdizimi koşulların paralel olarak değerlendirildiğini gösterirken, if...else-if değerlendirilmesini, koşulların sıralı ve öncelikli olarak değerlendirilmesini gerektirir.

Özellikle uygun olan başka programlar üreten programlar yazarken bu tür şeyleri yapmaya başladım.

Biz oradayken, Intel'in eski iHDL'sini kullanarak RTL yazarken,

   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

burada FORC..DOC..ENDCbir makro önişlemci döngü yapısıdır.

   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

Bu tek atama, zorunlu olmayan bir koddu, bu nedenle ilk ayar bitini bulmak gibi şeyler yapmanız gerekiyorsa, bir durum değişkeni ayarlanmasına izin verilmiyordu.

   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

Düşünmeye gel, bu tür yapılarla ilk karşılaştığım yer olabilir.

BTW, bazılarının if (0) stiline olan itirazları - else-if-koşullarının sırayla bağımlı olduğu ve keyfi olarak yeniden düzenlenemediği - RTL'deki AND ve OR ve XOR mantıklarına uygulanmaz - ancak devre && ve ||.


-1

Bunun hataları işlemek için kullanıldığını gördüm, örneğin

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

if(condition_fails)
   goto lable1;

Bu, goto hataları yönetmek için kullanıldığında yararlı olabilir, ifadeler yalnızca bir hata oluştuğunda çalıştırılır. Bunu çok eski C kodunda gördüm (burada fonksiyon argümanları '()' dışında yazılmıştır), kimsenin bunu takip ettiğini düşünmeyin.


-2

Bunu birkaç kez gördüm, en olası neden, kodun eski / farklı bir sürümü / dalında veya muhtemelen hata ayıklamak için bir şey değerlendirmek ve bunu değiştirmek if(0), ne varsa orada kaldırmak için biraz tembel bir yol olduğunu düşünüyorum .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.