http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
Andrey Tarasevich:
L'intera idea di usare 'fare/mentre 'versione è di creare una macro che sarà espandersi in un'istruzione regolare, non in un'istruzione composta. Questo è eseguito per rendere uniforme l'uso di macro in stile funzione con l'uso di di ordinarie funzioni in tutti i contesti.
Si consideri il seguente codice schizzo
if (<condition>)
foo(a);
else
bar(a);
dove 'foo' e 'bar' sono funzioni ordinarie. Ora immaginate che ti sentiresti di piace per sostituire la funzione 'foo' con una macro della natura sopra
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Ora, se la macro è definita in accordo con il secondo approccio (solo '{' e '} ') il codice non verrà più compilato, perché il' vero 'ramo di' if 'è ora rappresentato da un'istruzione composta. E quando hai metti un ';' dopo questa dichiarazione composta, hai terminato l'intera istruzione 'if' , rendendo quindi orfano il ramo 'else' (da cui l'errore di compilazione).
Un modo per correggere questo problema è ricordare di non inserire ";" dopo macro "invocazioni"
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
Questo compilerà e funzionano come previsto, ma questo non è uniforme. La soluzione più elegante è quella di assicurarsi che la macro si espanda in una normale istruzione , non in una composita. Un modo per raggiungere questo obiettivo è quello di definire la macro come segue
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Ora questo codice
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
compilerà senza problemi.
Tuttavia, notare la piccola ma importante differenza tra la mia definizione di CALL_FUNCS
e la prima versione nel messaggio. Non ho inserito uno ;
dopo il } while (0)
.Mettere un alla fine di quella definizione annullerebbe immediatamente l'intero punto dell'utilizzo di "do/while" e rendere quella macro praticamente equivalente alla versione dell'istruzione composta.
Non so perché l'autore del codice che hai citato nel tuo messaggio originale metta questo ;
dopo while (0)
. In questa forma entrambe le varianti sono equivalenti a . L'intera idea alla base della versione 'do/while' non è quella di includere questo finale ;
nella macro (per i motivi che ho spiegato sopra ).
Duplicati: http://stackoverflow.com/questions/923822/ e http://stackoverflow.com/questions/154136/ e http://stackoverflow.com/questions/257418/ – sth
In realtà c'è un altro modo per sistemare le cose. ({...}) può fare la stessa cosa di {} mentre (0). Rif: http://www.bruceblinn.com/linuxinfo/DoWhile.html – Nybble