Mehrere Erklärungen. Der erste ist allgemein, der zweite ist spezifisch für C-Präprozessor-Makros mit folgenden Parametern:
Ablaufsteuerung
Ich habe gesehen, dass dies in einfachem C-Code verwendet wird. Grundsätzlich ist es eine sicherere Version von goto, da Sie daraus ausbrechen können und der gesamte Speicher ordnungsgemäß bereinigt wird.
Warum sollte so etwas gotogut sein? Wenn Sie einen Code haben, in dem so gut wie jede Zeile einen Fehler zurückgeben kann, Sie jedoch auf alle gleich reagieren müssen (z. B. indem Sie den Fehler nach der Bereinigung Ihrem Anrufer übergeben), ist dies normalerweise besser lesbar, um einen Fehler zu vermeidenif( error ) { /* cleanup and error string generation and return here */ } als Es vermeidet das Duplizieren von Bereinigungscode.
In C ++ gibt es jedoch Ausnahmen + RAII für genau diesen Zweck, daher würde ich es als schlechten Codierungsstil betrachten.
Semikolonprüfung
Wenn Sie das Semikolon nach einem funktionsähnlichen Makroaufruf vergessen, werden Argumente möglicherweise unerwünscht kontrahiert und in eine gültige Syntax kompiliert. Stellen Sie sich das Makro vor
#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");
Das nennt man versehentlich als
if( foo )
PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
doSomethingElse();
Das "else" wird als mit dem verknüpft betrachtet gDebugModeOn, also wann fooistfalse , geschieht genau das Gegenteil von dem, was beabsichtigt war.
Bereitstellung eines Bereichs für temporäre Variablen.
Da das do / while geschweifte Klammern hat, haben temporäre Variablen einen klar definierten Bereich, dem sie nicht entkommen können.
Vermeiden Sie "möglicherweise unerwünschte Semikolon" -Warnungen
Einige Makros werden nur in Debug-Builds aktiviert. Sie definieren sie wie folgt:
#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n)
#endif
Wenn Sie dies nun in einem Release-Build innerhalb einer Bedingung verwenden, wird es kompiliert
if( foo )
;
Viele Compiler sehen dies als dasselbe an wie
if( foo );
Was oft versehentlich geschrieben wird. Sie erhalten also eine Warnung. Das do {} while (false) verbirgt dies vor dem Compiler und wird von ihm als Hinweis darauf akzeptiert, dass Sie es wirklich sind nichts tun möchten.
Vermeiden der Erfassung von Linien durch Bedingungen
Makro aus vorherigem Beispiel:
if( foo )
DBG_PRINT_NUM(42)
doSomething();
In einem Debug-Build wird dies nun problemlos kompiliert, da wir gewöhnlich auch das Semikolon eingefügt haben. Im Release-Build wird daraus jedoch plötzlich:
if( foo )
doSomething();
Oder klarer formatiert
if( foo )
doSomething();
Welches ist überhaupt nicht das, was beabsichtigt war. Durch Hinzufügen eines do {...} while (false) um das Makro wird das fehlende Semikolon in einen Kompilierungsfehler umgewandelt.
Was bedeutet das für das OP?
Im Allgemeinen möchten Sie Ausnahmen in C ++ für die Fehlerbehandlung und Vorlagen anstelle von Makros verwenden. In dem sehr seltenen Fall, in dem Sie noch Makros benötigen (z. B. beim Generieren von Klassennamen mithilfe des Einfügens von Token) oder auf einfaches C beschränkt sind, ist dies ein nützliches Muster.