2009-05-29 7 views

risposta

131

È possibile seguirlo con un punto e virgola e farlo apparire e agire più come una funzione. Funziona anche con clausole if/else in modo corretto allora.

Senza il tempo (0), il codice di cui sopra non avrebbe funzionato con

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

dal momento che il punto e virgola dopo la macro sarebbe "mangiare" la clausola else, e quanto sopra non sarebbe nemmeno la compilazione.

+5

Ma la domanda del PO stand. Perché non solo {(ptr) -> next ...} invece di fare {(ptr) -> next ...} while (0) ;? –

+26

arno ha spiegato che. Si espanderebbe in "{(ptr) -> next ...};" quindi, una dichiarazione seguita da una seconda affermazione. Se la sintassi è comunque "if (espressione) istruzione else statement". Il else non sarebbe associato a nessun se, dal momento che avresti scritto "if (expression) statement statement" (uno "{...}" e uno ";" statement). –

+3

Come ha detto Amo, è un trucco intelligente che consente a una macro di * essere * una dichiarazione C che deve terminare con un punto e virgola. Fa sì che la macro agisca esattamente come una chiamata di funzione, per quanto riguarda la costruzione di istruzioni e la terminazione (con ';'). – Eddie

41

Consente di raggruppare più istruzioni in un'unica macro.

Si supponga che hai fatto qualcosa di simile:

if (foo) 
    INIT_LIST_HEAD(bar); 

Se la macro è stata definita senza l'incapsulante fare {...} while (0) ;, il codice di cui sopra si espanderebbe a

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

Questo chiaramente non è ciò che era inteso, in quanto solo la prima affermazione verrà eseguita se si tiene premuto foo. La seconda affermazione verrebbe eseguita indipendentemente dal fatto che foo detenga.

Edit: Ulteriori spiegazioni a http://c-faq.com/cpp/multistmt.html e http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon

+7

Questo non spiega la parte do .. while (0) della macro, solo l'uso di {} parentesi. – SPWorley

+0

do {} mentre la parte (0) è spiegata nel post che questa è dup. – adobriyan

+1

SPWorley, adobriyan: in realtà, sembra che l'autore di questo post abbia aggiunto link che spiegano do {} while (0). – Jamer