2009-07-01 4 views
146

duplicados posibles:
What’s the use of do while(0) when we define a macro?
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
do { … } while (0) what is it good for?C de varias líneas macro: do/while (0) vs sección Cobertura

que he visto algunos multilínea C macros que están envueltos dentro de un ciclo do/while (0) como:

 
#define FOO \ 
    do { \ 
    do_stuff_here \ 
    do_more_stuff \ 
    } while (0) 

¿Cuáles son los beneficios (si los hay) de escribir el código de esa manera en lugar de utilizar un bloque básico:

 
#define FOO \ 
    { \ 
    do_stuff_here \ 
    do_more_stuff \ 
    } 
+4

Duplicados: http://stackoverflow.com/questions/923822/ y http://stackoverflow.com/questions/154136/ y http://stackoverflow.com/questions/257418/ – sth

+0

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

Respuesta

212

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).

+35

La publicación original fue hecha por mí en 'comp.lang.c'. 'bytes.com' aparentemente" se apropia "del contenido de' comp.lang.c' sin hacer ninguna referencia a la fuente. – AnT

Cuestiones relacionadas