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 \
  }
War es hilfreich?

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).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top