Pregunta

Posibles duplicados:
¿De qué sirve do while(0) cuando definimos una macro?
¿Por qué a veces hay declaraciones do/ while y if/else sin sentido en las macros C/C++?
do {… } while (0) ¿para qué sirve?

He visto algunas macros C multilínea que están envueltas dentro de un bucle 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 usar un bloque básico?

#define FOO \
  { \
    do_stuff_here \
    do_more_stuff \
  }
¿Fue útil?

Solución

http://bytes.com/groups/c/219859-do- while-0-macro-substitutions

Andréi Tarasevich:

La idea completa de usar la versión 'do/while' es hacer una macro que se expandirá en una declaración regular, no en una declaración compuesta.Esto se hace para hacer el uso de macros estilo función con el uso de funciones ordinarias en todos los contextos.

Considere el siguiente boceto de código

if (<condition>)
  foo(a);
else
  bar(a);

donde 'foo' y 'bar' son funciones ordinarias.Ahora imagine que le gustaría reemplazar la función 'foo' con una macro de la naturaleza anterior

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);

Ahora, si su macro se define de acuerdo con el segundo enfoque (solo '{' y '}'), el código ya no se compilará, porque la rama 'verdadera' de 'si' ahora está representada por una declaración compuesta.Y cuando pones un ';' Después de esta declaración compuesta, terminó la declaración 'si' completa, huérfana por la rama 'Else' (de ahí el error de compilación).

Una forma de corregir este problema es recordar no poner ';' Después de las "invocaciones" macro

if (<condition>)
  CALL_FUNCS(a)
else
  bar(a);

Esto se compilará y funcionará como se esperaba, pero no es uniforme.La solución más elegante es asegurarse de que la macro se expanda en una declaración regular, 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);

se 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 } while (0).poniendo un ; Al final de esa definición, derrotaría inmediatamente el punto de uso de 'hacer/while' y haría que esa macro sea prácticamente equivalente a la versión de condición compuesta.

No sé por qué el autor del código que citó en su mensaje original, ponga esto ; después while (0).En 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é anteriormente).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top