http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
Andrey Tarasevich:
La idea de utilizar 'hacer/while 'versión es para hacer una macro que se expandirá a en una declaración regular, no en una declaración compuesta. Esto es hecho para hacer el uso de macros de estilo de función uniformes con el uso de funciones ordinarias en todos los contextos.
considere el siguiente código boceto
if (<condition>)
foo(a);
else
bar(a);
donde 'foo' y 'bar' son funciones ordinarias. Ahora imagina que te gustaría gusta para reemplazar la función 'foo' con una macro de la naturaleza por encima de
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Ahora, si la macro se define de acuerdo con el segundo enfoque (justo '{' y '} ') el código ya no se compilará porque la rama' verdadera ' de' si 'ahora está representada por una instrucción compuesta. Y cuando ponga un ';' después de este enunciado compuesto, finalizó la instrucción completa 'if' , orientándose así a la rama 'else' (de ahí el error de compilación).
Una forma de corregir este problema es recordar no poner ';' después "invocaciones" macro
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
Esto compila y funciona como se esperaba, pero esto no es uniforme. La solución más elegante de es asegurarse de que la macro se expanda en una declaración normal , no en una compuesta. Una forma de lograrlo es definir la macro de la siguiente manera
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Ahora este código
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
compilará sin ningún problema.
Sin embargo, tenga en cuenta la pequeña pero importante diferencia entre mi definición de CALL_FUNCS
y la primera versión en su mensaje. No puse un ;
después de } while (0)
.Poner un ;
al final de esa definición vencería inmediatamente el punto completo de usar 'do/while' y hacer esa macro más o menos equivalente a la versión de declaración compuesta.
No sé por qué el autor del código que citó en su mensaje original puso esto ;
después de while (0)
. De esta forma, ambas variantes son equivalentes. Toda la idea detrás de usar la versión 'do/while' no es incluir esta final ;
en la macro (por las razones que expliqué arriba).
Duplicados: http://stackoverflow.com/questions/923822/ y http://stackoverflow.com/questions/154136/ y http://stackoverflow.com/questions/257418/ – sth
En realidad, hay otra manera de hacer las cosas bien. ({...}) puede hacer lo mismo que {} mientras (0). Ref: http://www.bruceblinn.com/linuxinfo/DoWhile.html – Nybble