¿Es una buena práctica usar macros C / C ++ como acceso directo para la compilación condicional?

13

Digamos que quiero tener varios tipos de mensajes de salida en mi código. Uno de ellos es DEBUG, que solo se imprime, cuando el código se compila en modo de depuración.

Por lo general, tendría que escribir algo como

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

que es bastante engorroso y molesto de usar en muchos lugares.

¿Es una buena práctica definir una macro para el fragmento de código, por lo que lo usaría de esta manera?

MSG_DEBUG("Debug message")

¿O hay alguna otra manera más elegante de cómo tratarlo sin macros? Estoy interesado en posibles soluciones tanto en C como en C ++, ya que estoy usando ambos lenguajes en diferentes proyectos.

Eenoku
fuente
No queda claro a partir de la pregunta por qué simplemente no pondría el código condicional en una función y llamaría a eso. ¿Hay alguna otra restricción que impida eso?
Alex
@gnat La pregunta que ha mencionado es tan amplia que la mayoría de las personas no la conectarían con este tema, especialmente cuando estarían buscando esta pregunta específica en Internet.
Eenoku
3
Su pregunta está etiquetada con c y c ++ , sin embargo, esos son lenguajes bastante diferentes. ¿Puedes aclarar de cuál estás hablando? Su ejemplo estaría perfectamente bien en C, pero podría implementarse mejor con un constexpr ifen C ++, por ejemplo.
Jörg W Mittag
1
Como un aparte, los diagnósticos deberían ir a STDERR. Además, ¿por qué no hacer que dependa de lo NDEBUGque assert()hace en su lugar? Entonces podría definirlo como #define DEBUG_MSG(MSG) assert(std::cerr << MSG), que también prueba el estado de flujo.
Deduplicador

Respuestas:

19

Claro, si está de acuerdo con el uso de macros en primer lugar, entonces definir una parametrizada en lugar de seguir repitiendo el mismo código condicional es ciertamente preferible por cualquier medida de buena codificación.

¿Deberías usar macros? En mi opinión, debería hacerlo, ya que es una práctica aceptada en C, y cualquier solución sin macro requeriría que al menos algo se ejecute incluso fuera del modo de depuración. El programador típico de C elegirá una macro ligeramente fea sobre el esfuerzo innecesario de tiempo de ejecución en cualquier momento.

Kilian Foth
fuente
13

Aquí hay un elemento de preferencia personal, pero en C ++ prefiero hacer esto en el archivo de encabezado:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

De modo que la función está en línea en las versiones de lanzamiento, pero es una función adecuada en la versión de depuración para que pueda tener una verificación de tipo adecuada, mensajes de error sensibles, etc. y la capacidad de agregar más funcionalidades (¿registro tal vez?) Más adelante.

Obviamente, también necesita encerrar la definición correspondiente de la función en el .cpparchivo en un #ifdef _DEBUGbloque.

Jack Aidley
fuente
Pero la sobrecarga de la llamada todavía está presente aquí, ¿no?
Eenoku
77
Si su compilador generará código para llamar a una función vacía conocida en una versión de lanzamiento, lo primero y más importante que debe hacer para mejorar la eficiencia es obtener un compilador mucho mejor. Esta es una optimización realmente trivial.
David Thornley
@Eenoku No, como dice David, será eliminado por cualquier compilador que deba usar.
Jack Aidley
3
Aquí hay una diferencia clave: la macro (dependiendo de cómo esté escrita) no evaluaría sus expresiones de argumento, mientras que la función siempre lo haría. Además, es un comportamiento indefinido pasar argumentos no triviales a las funciones varargs (y generalmente desencadena advertencias del compilador).
Sebastian Redl
2

Definitivamente, solo asegúrese de no pisar las pautas de código dadas por su equipo. Asegúrese de que ningún otro código en el sistema intente alcanzar la misma funcionalidad a través de una condición general if.

James O
fuente