Varias explicaciones El primero es general, el segundo es específico para macros de preprocesador C con parámetros:
Control de flujo
He visto esto usado en código C simple. Básicamente, es una versión más segura de goto, ya que puede salir de ella y toda la memoria se limpia correctamente.
¿Por qué algo gotobueno sería bueno? Bueno, si usted tiene código donde prácticamente cada línea puede devolver un error, pero que necesita para reaccionar a todos ellos de la misma manera (por ejemplo, mediante la presentación del error al que llama después de limpiar), por lo general es más fácil de leer para evitar una if( error ) { /* cleanup and error string generation and return here */ }como evita la duplicación del código de limpieza.
Sin embargo, en C ++ tiene excepciones + RAII exactamente para este propósito, por lo que lo consideraría un mal estilo de codificación.
Comprobación de punto y coma
Si olvida el punto y coma después de una invocación de macro similar a una función, los argumentos pueden contraerse de forma no deseada y compilarse en una sintaxis válida. Imagina la macro
#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");
Eso se llama accidentalmente como
if( foo )
PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
doSomethingElse();
El "más" se considerará asociado con el gDebugModeOn, por lo tanto, cuando foosea false, sucederá exactamente lo contrario de lo que se pretendía.
Proporcionando un alcance para variables temporales.
Dado que do / while tiene llaves, las variables temporales tienen un alcance claramente definido del que no pueden escapar.
Evitar advertencias de "punto y coma posiblemente no deseado"
Algunas macros solo se activan en versiones de depuración. Los define como:
#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n)
#endif
Ahora, si usa esto en una versión de lanzamiento dentro de un condicional, se compila a
if( foo )
;
Muchos compiladores ven esto como lo mismo que
if( foo );
Que a menudo se escribe accidentalmente. Entonces recibes una advertencia. Do {} while (false) oculta esto del compilador y es aceptado por él como una indicación de que realmente no desea hacer nada aquí.
Evitar la captura de líneas por condicionales
Macro del ejemplo anterior:
if( foo )
DBG_PRINT_NUM(42)
doSomething();
Ahora, en una compilación de depuración, ya que habitualmente también incluimos el punto y coma, esto se compila muy bien. Sin embargo, en la versión de lanzamiento, esto de repente se convierte en:
if( foo )
doSomething();
O más claramente formateado
if( foo )
doSomething();
Lo cual no es en absoluto lo que se pretendía. Agregar un do {...} while (falso) alrededor de la macro convierte el punto y coma faltante en un error de compilación.
¿Qué significa eso para el OP?
En general, desea utilizar excepciones en C ++ para el manejo de errores y plantillas en lugar de macros. Sin embargo, en el caso muy raro en el que todavía necesita macros (por ejemplo, cuando genera nombres de clase usando pegado de token) o está restringido a C simple, este es un patrón útil.