Bir #if 0… #endif bloğu tam olarak ne yapar?


124

Gelen C / C ++

Bir #if 0/ #endifbloğu arasına yerleştirilen koda ne olur ?

#if 0

//Code goes here

#endif

Kod basitçe atlanıyor ve bu nedenle yürütülmüyor mu?


17
Bu, büyük miktarlarda kodu yorumlamak veya kod bloklarının dahil edilmesinin test edilmesine izin vermek için kullanılan bir tekniktir. Bu özellik olmasaydı, her satırın //önüne veya ile bölüme başlayıp bölümü ile /*sonlandırmak gerekirdi */. İkinci tekniklerle ilgili sorun, yorumun iç içe geçmemesidir, bu nedenle geliştiricinin */başlangıç ​​ve bitiş arasındaki her şeyi kontrol etmesi ve işlemesi gerekir .
Thomas Matthews

Yanıtlar:


141

Sadece yürütülmez, derlenmez bile.

#ifgerçek derleme adımından önce değerlendirilen bir ön işlemci komutudur. Bu bloğun içindeki kod, derlenmiş ikili dosyada görünmez.

Genellikle kod bölümlerini daha sonra yeniden açmak amacıyla geçici olarak kaldırmak için kullanılır.


1
Bu, her türlü yorum için geçerlidir. Önemli fark yuvalanmadır.
Samy Bencherif

73

Tek bir önemli fark dışında, bloğu yorumlamakla aynıdır: Yuvalama bir sorun değildir. Bu kodu düşünün:

foo();
bar(x, y); /* x must not be NULL */
baz();

Yorum yapmak istersem şunları deneyebilirim:

/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/

Bzzt. Sözdizimi hatası! Neden? Blok yorumların iç içe geçmemesi nedeniyle (SO'nun sözdiziminin vurgulamasından da görebileceğiniz gibi) */"NULL" kelimesinden sonra gelen açıklama, bazçağrının yorum yapılmamasına ve */sonra bazda sözdizimi hatasına yol açarak yorumu sonlandırır . Diğer yandan:

#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif

Her şeyi yorumlamak için çalışıyor. Ve #if 0s'ler birbirleriyle yuva yapacaklar, şöyle ki:

#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif

Tabii ki bu biraz kafa karıştırıcı olabilir ve doğru yorumlanmazsa bakım sorunu haline gelebilir.


5
#İf içindeki kodun sözcüksel olarak doğru olması gerektiğini (yorumların aksine) ve önişlemci direktiflerinin hala yürürlükte olduğunu (aynen) unutmayın.
jpalecek

@David: Sözcük olarak doğru değil, ancak yine de derlenecek. Yani kodun sözcüksel olarak doğru olması gerekmez.
Dennis Zickefoose

1
@Dennis, gcc'den alıyorum foo.c:3: unterminated string or character constant, ne kullanıyorsun?
David X

18

Bu kodu kalıcı olarak yorumlar, böylece derleyici onu asla derlemez.

Kodlayıcı daha sonra, isterse kodun programda derlenmesi için #ifdef'i değiştirebilir.

Tıpkı kod yok gibi.


15

Bir #if 0… #endif bloğu tam olarak ne yapar?

Yazarın açıkça bir sürüm kontrol sistemi duymadığını söyler. Bu da size mümkün olduğunca uzağa kaçmanızı söyler ...


12

#elseVaka için eklemek istiyorum :

#if 0
   /* Code here will NOT be complied. */
#else
   /* Code will be compiled. */
#endif


#if 1
   /* Code will be complied. */
#else
   /* Code will NOT be compiled. */
#endif

7

Önişlemci # gördüğünde, sonraki belirtecin sıfır olmayan bir değere sahip olup olmadığını kontrol ederse. Varsa, derleyici için kodu etrafta tutar. Olmazsa, bu koddan kurtulur, böylece derleyici onu asla görmez.

Birisi # if 0 derse, kodu etkili bir şekilde yorumluyor, böylece asla derlenmeyecek. Bunu, sanki etrafına / * ... * / ekledikleri gibi düşünebilirsiniz. Tam olarak aynı değil, ama aynı etkiye sahip.

Ne olduğunu ayrıntılı olarak anlamak istiyorsanız, sık sık bakabilirsiniz. Pek çok derleyici, önişlemci çalıştıktan sonra dosyaları görmenize izin verir. Örneğin, Visual C ++ üzerinde switch / P komutu ön işlemciyi çalıştıracak ve sonuçları bir .i dosyasına koyacaktır.


Pek değil. Önişlemci belirteç yerine satıra göre ayrıştırır. Açıklamanıza göre mesela söylemek mümkün değil #if WIN32 || __CYGWIN__ama bu beklendiği gibi çalışıyor.
Ben Voigt

Basitleştiriyordum. Bir veya varsa, bu iki jetonun sıfırdan farklı olup olmadığını kontrol edecektir. Aynı şekilde bir varsa ve her ikisinin de sıfırdan farklı olup olmadığını kontrol edecektir.
Steve Rowe

3

Bir ile başlayan satırlar #vardır önişlemci direktifleri . #if 0 [...] #endifbloklar derleyiciye ulaşmaz ve makine kodu oluşturmaz.

Bir kaynak dosyayla önişlemciye ne olduğunu gösterebilirsiniz ifdef.cxx:

#if 0
This code will not be compiled
#else
int i = 0;
#endif

Koşu gcc -E ifdef.cxx size neyin derlendiğini gösterecektir.

Geliştirme döngüsü sırasında bir kod bloğunun derlenmesini önlemek için bu mekanizmayı kullanmayı tercih edebilirsiniz, ancak kodunuza sadece hamleler eklediği ve okunabilirliği azalttığı için muhtemelen onu kaynak kontrolünüze eklemek istemezsiniz. Yorumlanmış tarihsel bir kod parçasıysa, kaldırılması gerekir: kaynak kontrolü geçmişi içerir, değil mi?

Ayrıca, cevap her ikisi için aynı olabilir C ve C ++ ancak C / C ++ ve denir hiçbir dil, böyle bir dili belirtmek için iyi bir alışkanlıktır orada yer etmedi.


4
C / C ++ 'yı "C veya C ++" için kısaltma olarak söylemenin nesi yanlış? "C / C ++" adında bir dil olduğunu düşünen birinin kafasının karışacağını gerçekten düşünüyor musunuz?
Christopher Barber

1
@Chris: İnsanlar sürekli olarak "C / C ++ 'da X'i nasıl yaparım?" Saçma bir soru olan; birini veya diğerini kodluyorsunuz ve henüz seçmediyseniz, bu konuda açık olmalısınız. Yani, evet, insanlar "C / C ++" adlı bir dil olduğu konusunda kafaları karıştı
Dennis Zickefoose

1
Ne saçma bir ifade! Cevapları hem C hem de C ++ ile ilgili olan binlerce soru var. Bunun soru sormak için bir site olduğunu unutmayın. Sırf genel bir soru soruyor olmanız, hangi dili kullandığınızı bilmediğiniz anlamına gelmez. Bu soruda olduğu gibi durumun böyle olduğundan şüpheleniyorsanız, C veya C ++ 'yı belirtmek nasıl yardımcı olur? C veya C ++ için geçerli olabilecek her sorunun iki kez sorulmasının yararlı olacağını düşünüyor musunuz?
Christopher Barber

@Christopher: Haklısın, cevapların C, C ++ ve Objective-C ile aynı derecede alakalı olduğu birçok soru var (bu onlardan biri). Stack Overflow, bir sorunun hangi dillere ait olduğunu belirtmek için kullanışlı bir etiketleme sistemine sahiptir. @Dennis'in belirttiği gibi, SO (ve diğer programlama forumları [fora?]), C ile bu dillere birbirinin yerine C / C ++ olarak atıfta bulunan diğer C türevi diller arasındaki tasvir konusunda kafası karışan (çok) birçok insan var. soruyu uygun dilde cevaplamak daha zor.
Johnsyweb

2

Pek değil

int main(void)
{
   #if 0
     the apostrophe ' causes a warning
   #endif
   return 0;
}

Gcc 4.2.4 ile "tc: 4: 19: uyarı: eksik sonlandırma 'karakteri" gösterir.


2
Bu uyarı derleyici tarafından değil, önişlemci tarafından oluşturulur. Derleyici yalnızca şunu görür: # 1 "tc" # 1 "<built-in>" # 1 "<command-line>" # 1 "tc" int main (void) {return 0; }
Johnsyweb

0

Yorum yapmanın ucuz bir yolu, ancak hata ayıklama potansiyeline sahip olabileceğinden şüpheleniyorum. Örneğin, değerleri bir dosyaya çıkaran bir yapıya sahip olduğunuzu varsayalım. Bunu son sürümde istemeyebilirsiniz, böylece #if 0 ... #endif kullanabilirsiniz.

Ayrıca, hata ayıklama amacıyla bunu yapmanın daha iyi bir yolunun aşağıdakileri yapmaktan şüpheleniyorum:

#ifdef DEBUG
// output to file
#endif

Bunun gibi bir şey yapabilirsiniz ve bu daha mantıklı olabilir ve tek yapmanız gereken sonuçları görmek için DEBUG'ı tanımlamaktır.

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.