C mehrzeiligen Makro: do / while (0) vs Umfang Block [Duplikat]
Frage
Mögliche Duplikate:
Was ist die Verwendung von do while (0), wenn wir definieren ein Makro?
Warum gibt es manchmal bedeutungslos do / while und if / else-Anweisungen in C / C ++ Makros?
do {...} while (0), was für sie gut ist?
Ich habe einige mehrzeiligen C-Makros zu sehen, die in einem do gewickelten / while (0) Schleife wie:
#define FOO \ do { \ do_stuff_here \ do_more_stuff \ } while (0)
Was sind die Vorteile (falls vorhanden) der Codes, die Art und Weise zu schreiben, im Gegensatz einen Basisblock zu verwenden:
#define FOO \ { \ do_stuff_here \ do_more_stuff \ }
Lösung
http://bytes.com/groups/c/ 219.859-do-while-0-Makro-Ersetzungen
Andrey Tarasevich:
Die ganze Idee der Verwendung von ‚do / while‘ -Version ein Makro zu machen, ist das Produkt sei erweitern in eine reguläre Anweisung, nicht in einer zusammengesetzten Anweisung. Das ist getan, um den Einsatz von funktions Stil Makros mit der einheitlich zu machen Verwendung von gewöhnlichen Funktionen in allen Kontexten.
Betrachten Sie den folgenden Code Skizze
if (<condition>)
foo(a);
else
bar(a);
Dabei steht 'foo' und 'bar' sind ganz normale Funktionen. Nun stell dir vor, dass du würdest wie Funktion ‚foo‘ mit einem Makro der oben genannten Art ersetzen
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Nun, wenn Ihr Makro wird in Übereinstimmung mit dem zweiten Ansatz definiert (Nur ‚{‘ und ‚}‘) wird der Code nicht mehr kompilieren, weil die ‚wahre‘ Zweig der ‚if‘ wird nun durch eine zusammengesetzte Anweisung dargestellt. Und wenn du legt eine ‚;‘ nach dieser zusammengesetzten Anweisung, beendet man die ganze ‚if‘ Aussage, so verwaisen die ‚else‘ Zweig (daher der Übersetzungsfehler).
Eine Möglichkeit, dieses Problem zu beheben, ist daran zu erinnern, nicht zu setzen ‚;‘ nach Makro "Beschwörungen"
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
Dies kompiliert und wie erwartet, aber dies ist nicht einheitlich. Das elegantere Lösung ist, um sicherzustellen, dass Makro in ein reguläres erweitern Anweisung, nicht in eine Verbindung ein. Eine Möglichkeit, das zu erreichen ist zu definieren, das Makro wie folgt
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Dieser Code
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
wird ohne Probleme kompilieren.
Beachten Sie jedoch, den kleinen, aber wichtigen Unterschied zwischen meiner Definition
von CALL_FUNCS
und der ersten Version in Ihrer Nachricht. Ich habe kein setzen
;
nach } while (0)
. Einlochen ;
am Ende dieser Definition
würde sofort den gesamten Punkt Niederlage der Verwendung von ‚do / while‘ und machen
dass Makro ziemlich gleichbedeutend mit der Verbindung-Anweisung Version.
Ich weiß nicht, warum der Autor des Codes Sie in Ihrem ursprünglichen zitiert
Nachricht setzen diese ;
nach while (0)
. In dieser Form sind beide Varianten
Äquivalent. Die ganze Idee hinter der Verwendung ‚do / while‘ -Version ist nicht zu
umfassen diese letzte ;
in das Makro (aus den Gründen, die ich erklärt
oben).