Was genau macht ein #if 0… #endif Block?

124

In C / C ++

Was passiert mit Code zwischen einem #if 0/ #endifBlock?

#if 0

//Code goes here

#endif

Wird der Code einfach übersprungen und daher nicht ausgeführt?

vette982
quelle
17
Dies ist eine Technik, mit der große Codemengen auskommentiert oder das Einschließen von Codeblöcken getestet werden können. Ohne diese Funktion müsste man entweder jeder Zeile ein Präfix voranstellen //oder den Abschnitt mit beginnen /*und den Abschnitt mit beenden */. Das Problem bei letzteren Techniken ist, dass Kommentare nicht verschachtelt sind, sodass der Entwickler */zwischen Start und Ende prüfen und behandeln muss .
Thomas Matthews

Antworten:

141

Es wird nicht nur nicht ausgeführt, sondern auch nicht kompiliert.

#ifist ein Präprozessorbefehl, der vor dem eigentlichen Kompilierungsschritt ausgewertet wird. Der Code in diesem Block wird nicht in der kompilierten Binärdatei angezeigt.

Es wird häufig zum vorübergehenden Entfernen von Codesegmenten verwendet, um sie später wieder einzuschalten.

David
quelle
1
Dies gilt für jede Art von Kommentar. Der wichtige Unterschied ist das Verschachteln.
Samy Bencherif
73

Es ist identisch mit dem Auskommentieren des Blocks, außer mit einem wichtigen Unterschied: Das Verschachteln ist kein Problem. Betrachten Sie diesen Code:

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

Wenn ich es auskommentieren möchte, könnte ich versuchen:

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

Bzzt. Syntax-Fehler! Warum? Da Blockkommentare nicht verschachtelt sind, wird (wie Sie anhand der Syntaxhervorhebung von SO sehen können) */der Kommentar nach dem Wort "NULL" beendet, wodurch der bazAufruf nicht auskommentiert wird, und */nach bazeinem Syntaxfehler. Andererseits:

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

Funktioniert, um die ganze Sache zu kommentieren. Und die #if 0s werden wie folgt miteinander nisten:

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

Obwohl dies natürlich etwas verwirrend werden und zu Wartungsproblemen führen kann, wenn es nicht richtig kommentiert wird.

Tyler McHenry
quelle
5
Beachten Sie nur, dass der Code in #if lexikalisch korrekt sein muss (im Gegensatz zu Kommentaren) und Präprozessor-Direktiven noch in Kraft sind (dito).
Jpalecek
@ David: Es ist nicht lexikalisch korrekt, aber es wird trotzdem kompiliert. Der Code muss also nicht lexikalisch korrekt sein.
Dennis Zickefoose
1
@ Tennis, ich bekomme foo.c:3: unterminated string or character constantvon gcc, was benutzt du?
David X
18

Dieser Code wird permanent auskommentiert, sodass der Compiler ihn niemals kompiliert.

Der Codierer kann später das #ifdef ändern, damit dieser Code im Programm kompiliert wird, wenn er möchte.

Es ist genau so, als ob der Code nicht existiert.

Nilbert
quelle
15

Was genau macht ein #if 0… #endif Block?

Es sagt Ihnen, dass der Autor offensichtlich noch nie von einem Versionskontrollsystem gehört hat. Was Ihnen wiederum sagt, dass Sie so weit wie möglich weglaufen sollen…

Jörg W Mittag
quelle
12

Ich möchte für den #elseFall hinzufügen :

#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
Steven Xu
quelle
7

Wenn der Präprozessor #if sieht, prüft er, ob das nächste Token einen Wert ungleich Null hat. Wenn dies der Fall ist, bleibt der Code für den Compiler erhalten. Wenn dies nicht der Fall ist, wird dieser Code entfernt, sodass der Compiler ihn nie sieht.

Wenn jemand #if 0 sagt, kommentiert er den Code effektiv aus, sodass er niemals kompiliert wird. Sie können sich das genauso vorstellen, als hätten sie / * ... * / darum gelegt. Es ist nicht ganz dasselbe, aber es hat den gleichen Effekt.

Wenn Sie verstehen möchten, was im Detail passiert ist, können Sie oft nachsehen. Bei vielen Compilern können Sie die Dateien anzeigen, nachdem der Präprozessor ausgeführt wurde. In Visual C ++ führt der Befehl switch / P beispielsweise den Präprozessor aus und speichert die Ergebnisse in einer .i-Datei.

Steve Rowe
quelle
Nicht ganz. Der Präprozessor analysiert eher nach Zeilen als nach Token. Nach Ihrer Erklärung wäre es nicht möglich, zB zu sagen, #if WIN32 || __CYGWIN__aber dies funktioniert wie erwartet.
Ben Voigt
Ich habe vereinfacht. Wenn es ein oder gibt, wird geprüft, ob eines der Token nicht Null ist. Ebenso, wenn es ein und gibt, wird geprüft, ob beide nicht Null sind.
Steve Rowe
3

Zeilen, die mit a beginnen, #sind Präprozessoranweisungen . #if 0 [...] #endifBlöcke schaffen es nicht zum Compiler und generieren keinen Maschinencode.

Sie können anhand einer Quelldatei demonstrieren, was mit dem Präprozessor passiert ifdef.cxx:

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

Laufen gcc -E ifdef.cxx zeigt Ihnen, was kompiliert wird.

Sie können diesen Mechanismus verwenden, um zu verhindern, dass ein Codeblock während des Entwicklungszyklus kompiliert wird, aber Sie möchten ihn wahrscheinlich nicht in Ihre Quellcodeverwaltung einchecken, da er Ihrem Code nur Cruft hinzufügt und die Lesbarkeit verringert. Wenn es sich um einen historischen Code handelt, der auskommentiert wurde, sollte er entfernt werden: Die Quellcodeverwaltung enthält den Verlauf, oder?

Auch die Antwort mag für C und C ++ gleich sein, aber es gibt keine Sprache namens C / C ++ und es ist keine gute Angewohnheit, sich auf eine solche Sprache zu beziehen.

Johnsyweb
quelle
4
Was ist falsch daran, C / C ++ als Abkürzung für "C oder C ++" zu sagen? Glauben Sie wirklich, dass jemand verwirrt sein wird, wenn er denkt, dass es eine Sprache namens "C / C ++" gibt?
Christopher Barber
1
@Chris: Die Leute stellen ständig Fragen wie "Wie mache ich X in C / C ++?" Welches ist eine unsinnige Frage; Sie codieren in der einen oder anderen, und wenn Sie noch nicht ausgewählt haben, sollten Sie dies ausdrücklich angeben. Also, ja, die Leute sind verwirrt darüber, dass es eine Sprache namens "C / C ++" gibt
Dennis Zickefoose
1
Was für eine unsinnige Aussage! Es gibt Tausende von Fragen, deren Antworten sowohl für C als auch für C ++ relevant sind. Denken Sie daran, dass dies eine Seite ist, auf der Sie Fragen stellen können. Nur weil Sie eine allgemeine Frage stellen, heißt das nicht, dass Sie nicht wissen, welche Sprache Sie verwenden. Wenn Sie den Verdacht haben, dass dies der Fall ist, wie in dieser Frage, wie hilft es, C oder C ++ anzugeben? Halten Sie es für hilfreich, wenn jede Frage, die für C oder C ++ gelten könnte, zweimal gestellt wird?
Christopher Barber
@Christopher: Sie haben Recht, es gibt viele Fragen, bei denen die Antworten für C, C ++ und Objective-C genauso relevant sind (dies ist eine davon). Stack Overflow verfügt über ein praktisches Tagging-System, mit dem angegeben werden kann, zu welchen Sprachen eine Frage gehört. Wie @Dennis erwähnt, gibt es SO (und andere Programmierforen [Foren?]) (Zu) viele Leute, die hinsichtlich der Abgrenzung zwischen C und anderen C-abgeleiteten Sprachen verwirrt sind und diese Sprachen austauschbar als C / C ++ bezeichnen schwieriger, die Frage in der entsprechenden Sprache zu beantworten.
Johnsyweb
2

Nicht ganz

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

Es zeigt "tc: 4: 19: Warnung: fehlendes Abschlusszeichen" mit gcc 4.2.4

Arthur Kalliokoski
quelle
2
Diese Warnung wird vom Präprozessor und nicht vom Compiler generiert. Der Compiler sieht nur: # 1 "tc" # 1 "<built-in>" # 1 "<Befehlszeile>" # 1 "tc" int main (void) {return 0; }
Johnsyweb
0

Es ist eine billige Möglichkeit, Kommentare abzugeben, aber ich vermute, dass dies ein Debugging-Potenzial haben könnte. Angenommen, Sie haben einen Build, der Werte in eine Datei ausgibt. Möglicherweise möchten Sie dies nicht in einer endgültigen Version, sodass Sie #if 0 ... #endif verwenden können.

Ich vermute auch, dass ein besserer Weg, dies zu Debug-Zwecken zu tun, darin besteht, Folgendes zu tun:

#ifdef DEBUG
// output to file
#endif

Sie können so etwas tun, und es könnte sinnvoller sein. Sie müssen lediglich DEBUG definieren, um die Ergebnisse anzuzeigen.

Daniel
quelle