Das gcc-Dokumentation für cpp über die erklären #if
Richtlinie:
[…] und logische Operationen (&& und ||). Die beiden letzteren gehorchen den üblichen Kurzschlussregeln des Standards C.
Was bedeutet das? Es gibt keine Auswertung von Ausdrücken während der Vorverarbeitung, wie kann es also kurzgeschlossen werden?
Ganz einfach: Undefinierte Makros haben den numerischen Wert Null, und die Division durch Null ist illegal.
#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif
#if
wertet den Rest seiner Zeile als ganzzahligen konstanten Ausdruck aus. Ihre verlinkte Dokumentation beginnt:
Mit der ‘#if’-Direktive können Sie den Wert eines arithmetischen Ausdrucks testen, anstatt nur die Existenz eines Makros.
Das ist keine gcc-Erweiterung, die Standard-Syntax für #if
ist
#if
constant-expression new-line group
opt
.
Der C99-Präprozessor behandelt alle Konstanten als [u]intmax_t
.
Worauf sie sich beziehen, ist &&
und ||
Betreiber für #if
#if defined (AAA) || defined (BBB)
Wenn defined (AAA)
ist dann definiert defined (BBB)
wird nie ausgewertet.
AKTUALISIEREN
Das Ausführen der Berechnung wird also kurzgeschlossen. Zum Beispiel, wenn Sie mit bauen -Wundef
um vor der Verwendung von undefinierten Makros zu warnen.
#if defined FOO && FOO > 1000
#endif
#if FOO > 1000
#endif
wird darin enden, dass
thomas:~ jeffery$ gcc foo.c -Wundef
foo.c:4:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef]
#if FOO > 1000
^
1 warning generated.
Die erste Version generiert also nicht die undefinierte Makrowarnung, weil FOO > 1000
wird nicht ausgewertet.
ALTE SÜSSE
Dies wird wichtig, wenn der zweite Teil ein Makro ist, das Nebenwirkungen hat. Das Makro würde nicht ausgewertet, daher würden die Seiteneffekte nicht stattfinden.
Um Makromissbrauch zu vermeiden, gebe ich ein einigermaßen vernünftiges Beispiel
#define FOO
#define IF_WARN(x) _Pragma (#x) 1
#if defined(FOO) || IF_WARN(GCC warning "FOO not defined")
#endif
Nachdem ich dieses Beispiel erstellt habe, stoße ich nun auf ein Problem. IF_WARN
wird immer ausgewertet.
huh, mehr Forschung erforderlich.
Tja foo… jetzt wo ich es nochmal gelesen habe.
Makros. Alle Makros im Ausdruck werden erweitert, bevor die eigentliche Berechnung des Werts des Ausdrucks beginnt.
Es gibt keine Auswertung von Ausdrücken während der Vorverarbeitung, wie kann es also kurzgeschlossen werden?
Ja, der Ausdruck wird während der Vorverarbeitung ausgewertet.
C11: 6.10.1 Bedingte Einbeziehung (p4):
Vor der AuswertungMakroaufrufe in der Liste der Vorverarbeitungstoken, die zu …
In einer Fußnote 166:
Weil die Die Steuerung des konstanten Ausdrucks wird während der Übersetzungsphase 4 ausgewertetalle Kennungen….
Diese Aussagen belegen dies eindeutig Es gibt eine Auswertung des Ausdrucks in der Vorverarbeitung. Die notwendige Bedingung ist, dass der steuernde Ausdruck einen ganzzahligen Wert ergeben muss.
Jetzt der Betreiber &&
und ||
befolgen die üblichen Kurzschlussregeln der Norm C, wie in angegeben GNU-Dokument.
Führen Sie nun dieses Programm mit und ohne aus //
und sehen Sie sich das Ergebnis an, um das Kurzschlussverhalten zu sehen:
#include<stdio.h>
#define macro1 1
//#define macro2 1
int main( void )
{
#if defined (macro1) && defined (macro2)
printf( "Hello!\n" );
#endif
printf("World\n");
return 0;
}
Das Auswerten von Makrobedingungen ist ein Teil (ein Hauptteil) der Vorverarbeitung, daher tritt es auf und das Kurzschließen ist dort sinnvoll. Sie können Beispiele für die anderen Antworten sehen.
EIN bedingt ist eine Direktive, die die anweist Präprozessor um auszuwählen, ob ein Stück Code in den endgültigen Token-Stream aufgenommen werden soll, der an den Compiler übergeben wird. Präprozessor-Bedingungen kann arithmetische Ausdrücke testen oder ob ein Name als Makro definiert ist oder beides gleichzeitig mit dem speziellen definierten Operator.†
Außerdem es kann Kompilierzeit reduzieren. Das Verändern der folgenden Auswertungen kann die Kompilierung beschleunigen (abhängig von der Implementierung eines Compilers).
Ich denke, Kurzschluss bedeutet hier, den zweiten Term nicht auszuwerten, wenn die Auswertung des ersten Terms den resultierenden Wert vollständig bestimmt
– jean-loup
4. Juni 2014 um 12:38 Uhr
Aber wie kann man das sagen? Warum sollte das wichtig sein?
– Aschepler
4. Juni 2014 um 12:39 Uhr
Interessante Frage.
– Leichtigkeitsrennen im Orbit
4. Juni 2014 um 12:43 Uhr
In Standard-C,
#if
will nur einen konstanten Ausdruck. Wenn dieser konstante Ausdruck istmy_const1 && my_const2
dann wird der Ausdruck so ausgewertet, wie er an anderer Stelle im Code gewesen wäre, so einfach ist das. Aber ich bin mir sicher, dass GCC viele seltsame, überflüssige Erweiterungen für den Präprozessor hat, also scheint der Kommentar für sie zu gelten.– Ludin
4. Juni 2014 um 13:26 Uhr
Woher wissen Sie, dass hier keine Auswertung von Ausdrücken während der Vorverarbeitung erfolgt?
– Hacken
4. Juni 2014 um 14:29 Uhr