Schauen Sie sich diese Zeile an:
%Vor% __assert
ist eine Funktion, die eine Assertion-Nachricht, einen Dateinamen und eine Zeilennummer als Argumente akzeptiert. Im Grunde ist dies die Methode, die die Fehlermeldung ausgibt und das Programm beendet, wenn die Assertion fehlgeschlagen ist.
Sehen Sie sich dann die obige Makrodefinition an:
%Vor% Er definiert das assert(EX)
-Makro so, dass er zuerst den EX-Ausdruck und (wegen der Kurzschlussoperation des C ++ ||
-Operators) nur dann, wenn es fehlschlägt, die __assert
-Funktion aufruft und die gescheiterte Assertionsausnahme als Zeichenfolge und die genaue Position des assert()
-Methodenaufrufs in Ihren Quelldateien. Mit dieser Preprozessor-Trickserei erreicht die Assertion-Library das, wenn Sie in Ihrem Programm Folgendes eingeben:
und Ihre Assertion schlägt während des Programmlaufs fehl, erhalten Sie das detaillierte
%Vor%Fehlermeldung, die Ihnen hilft, den genauen Speicherort der Assertion in Ihrem Code zu identifizieren.
Der (void)
-Teil ist nur dafür da, dass der Compiler keine Warnungen über das ungenutzte Ergebnis des (EX) || 0
Ausdrucks ausgibt, siehe die anderen Antworten, die Jungs haben das gut erklärt.
Der verbleibende Präprozessor define NDEBUG
wird verwendet, um die Generierung der Assertion während der gesamten Kompilierungszeit einzuschalten. Ihre resultierende ausführbare Datei wird kleiner und schneller sein.
__assert
ist Teil der Implementierung; in diesem Fall eine Funktion in der Bibliothek, die im Falle eines Assertionsfehlers aufgerufen wird. Und das (void)
besteht einfach darin, Compiler-Warnungen über die nicht verwendeten Ergebnisse des ||
-Operators zu schließen.
Es unterdrückt Compiler-Warnungen über nicht verwendete Werte oder Variablen.
Beachten Sie auch den Komma-Operator auf der rechten Seite, der beide Seiten von ||
etwas macht, das in bool konvertiert werden kann.
__assert
ist eine interne Funktion, die vermutlich eine Nachricht druckt und das erforderliche Assertionsverhalten implementiert (d. h. Aufruf abort()
).
Fast ...
Betrachte: assert( a == 0 );
Dies wird zu
(void)((a == 0) || (__assert (#a == 0, __FILE__, __LINE__),0))
Wenn Sie den Ausdruck (x || y)
haben - In diesem Fall werden sowohl x als auch y als bools ausgewertet. Wenn also 'a' zu 0 wird, wird die Definition von || sagt, um das nächste Bool in der Reihe zu versuchen, zB 'y'
Also - wenn Ihre Behauptung falsch ist, wird (__assert (#a == 0, __FILE__, __LINE__),0)
ausgewertet, was bedeutet, dass __assert()
aufgerufen wird.
Warum das (__assert (), 0) ?? __asset ist eine Funktion, die als void __assert()
- naja ... die meiste Zeit definiert ist. siehe Ссылка für einen Satz assert () Makros - beachte das alles von ihnen am Ende eine Funktion aufrufen ...
Mit dem Komma-Operator können Sie zwei Dinge in der gleichen Anweisung tun, dh i++, j++
- aber denken Sie daran, dass ein Ausdruck zu einem Wert - in diesem Fall zu der "0" - ausgewertet werden muss Die gesamte Anweisung wird in (void)(0 || 0)
ausgewertet, was ein gültiger Ausdruck ist. Als Nebeneffekt wird Ihr Ausdruck ausgewertet und möglicherweise eine Funktion aufgerufen.
Hinweis in (void)(0 || 0)
Die erste 0 stammt von Ihrer fehlgeschlagenen Assertion. Dies kann zur Kompilierzeit erzeugt werden, wenn Ihre Assertion etwas auswertet, das der Compiler als Konstante erzeugen kann, oder einen Ausdruck, der ausgewertet wird, zB (void)((a == 0) || 0)
Beachten Sie das Komma ", 0" ist für wirklich pedantische Compiler - ich sehe es normalerweise nicht. Aber die (a || __assert())
ist sehr häufig. Sie könnten das Makro als
Tags und Links c++ assert implementation