Was nützt do while(0), wenn wir ein Makro definieren? [duplicate]

Lesezeit: 3 Minuten

Benutzeravatar von amazingjxq
erstaunlichjxq

Mögliche Duplikate:

Do-While- und if-else-Anweisungen in C/C++-Makros
do { … } while (0) — wozu ist es gut?

Ich lese den Linux-Kernel und habe viele Makros wie diese gefunden:

#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

Warum verwenden sie dies, anstatt es einfach in einem {} zu definieren?

Sie können ihm ein Semikolon folgen lassen und es eher wie eine Funktion aussehen und verhalten. Es funktioniert dann auch mit if/else-Klauseln einwandfrei.

Ohne das while(0) würde Ihr obiger Code nicht funktionieren

if (doit) 
   INIT_LIST_HEAD(x);
 else 
   displayError(x);

da das Semikolon nach dem Makro die Else-Klausel “fressen” würde und das obige nicht einmal kompilieren würde.

  • Aber die Frage des OP steht. Warum nicht einfach { (ptr)->next … } statt do { (ptr)->next … } while (0);?

    – joshk0

    29. Mai 2009 um 0:26 Uhr

  • Arno hat das erklärt. Es würde sich erweitern zu “{ (ptr)->next … };” also eine Anweisung gefolgt von einer zweiten Anweisung. Die If-Syntax lautet jedoch “if ( expression ) statement else statement” . Das else wäre keinem if zugeordnet, da Sie „if ( expression ) statement statement“ geschrieben hätten (eine „{ … }“- und eine „;“-Anweisung).

    – Johannes Schaub – litb

    29. Mai 2009 um 0:37 Uhr

  • Wie Amo sagte, ist es ein cleverer Trick, der es einem Makro ermöglicht sein eine C-Anweisung, die mit einem Semikolon enden muss. Dadurch verhält sich das Makro genau wie ein Funktionsaufruf, was den Aufbau und die Beendigung der Anweisung (mit ‘;’) betrifft.

    – Edi

    29. Mai 2009 um 1:53 Uhr

  • Beachten Sie jedoch, dass in diesem Fall alles völlig unnötig ist, da der Hauptteil des Makros viel sauberer geschrieben werden könnte als: (ptr)->next=(ptr)->prev=(ptr).

    – Jerry Sarg

    2. Dezember 2009 um 4:19 Uhr

  • @JoshK Die Schleife wird nur einmal ausgeführt, da while(0) eine falsche Bedingung ist. Ein optimierender Compiler wird sich jedoch davon befreien do {stat}while(0) & durch nur ersetzen stat weil es sowieso nur einmal passiert.

    – Karim Manauil

    5. September 2017 um 19:01 Uhr

Benutzeravatar von rodion
Rodion

Es ermöglicht Ihnen, mehrere Anweisungen in einem Makro zu gruppieren.

Angenommen, Sie haben Folgendes getan:

if (foo) 
    INIT_LIST_HEAD(bar);

Wenn das Makro ohne das kapselnde do { … } while (0); definiert wurde, würde der obige Code zu erweitern

if (foo)
    (bar)->next = (bar);
    (bar)->prev = (bar);

Dies ist eindeutig nicht beabsichtigt, da nur die erste Anweisung ausgeführt wird, wenn foo gilt. Die zweite Anweisung würde unabhängig davon ausgeführt, ob foo gilt.

Edit: Weitere Erläuterungen unter http://c-faq.com/cpp/multistmt.html und http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon

  • Dies erklärt nicht den do .. while(0)-Teil des Makros, sondern nur die Verwendung von {} geschweiften Klammern.

    – SPWorley

    29. Mai 2009 um 18:05 Uhr

  • do {} while (0) Teil wird in dem Beitrag erklärt, von dem dieser dup ist.

    – Adobebryan

    8. Juli 2011 um 9:48 Uhr

  • SPWorley, adobriyan: Tatsächlich sieht es so aus, als hätte der Autor dieses Posts Links hinzugefügt, die das do {} while (0) erklären.

    – Paul Merrill

    12. März 2012 um 2:11 Uhr

1423710cookie-checkWas nützt do while(0), wenn wir ein Makro definieren? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy