Intentando crear una macro que se pueda usar para imprimir mensajes de depuración cuando se define DEBUG, como el siguiente pseudocódigo:
#define DEBUG 1
#define debug_print(args ...) if (DEBUG) fprintf(stderr, args)
¿Cómo se logra esto con una macro?
Entonces, cuando uso gcc, me gusta:
#define DBGI(expr) ({int g2rE3=expr; fprintf(stderr, "%s:%d:%s(): ""%s->%i\n", __FILE__, __LINE__, __func__, #expr, g2rE3); g2rE3;})
Porque se puede insertar en el código.
Supongamos que está tratando de depurar
printf("%i\n", (1*2*3*4*5*6));
720
Entonces puedes cambiarlo a:
printf("%i\n", DBGI(1*2*3*4*5*6));
hello.c:86:main(): 1*2*3*4*5*6->720
720
Y puede obtener un análisis de qué expresión se evaluó a qué.
Está protegido contra el problema de la doble evaluación, pero la ausencia de gensyms lo deja abierto a colisiones de nombres.
Sin embargo anida:
DBGI(printf("%i\n", DBGI(1*2*3*4*5*6)));
hello.c:86:main(): 1*2*3*4*5*6->720
720
hello.c:86:main(): printf("%i\n", DBGI(1*2*3*4*5*6))->4
Así que creo que mientras evite usar g2rE3 como nombre de variable, estará bien.
Ciertamente lo he encontrado (y versiones aliadas para cadenas y versiones para niveles de depuración, etc.) invaluable.
#define PRINT_LOG(str_format, ...) { \
time_t curtime=time (NULL); \
struct tm *ltm = localtime (&curtime); \
printf("[%d-%02d-%02d %02d:%02d:%02d] " str_format, \
ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, \
ltm->tm_hour, ltm->tm_min, ltm->tm_sec, ##__VA_ARGS__); \
}
PRINT_LOG("[%d] Serving client, str=%s, number=%d\n", getpid(), "my str", 10);
De acuerdo a http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.htmldebe haber un ##
antes de __VA_ARGS__
.
De lo contrario, una macro #define dbg_print(format, ...) printf(format, __VA_ARGS__)
no compilará el siguiente ejemplo: dbg_print("hello world");
.
Esto es lo que uso:
#if DBG
#include <stdio.h>
#define DBGPRINT printf
#else
#define DBGPRINT(...) /**/
#endif
Tiene el gran beneficio de manejar printf correctamente, incluso sin argumentos adicionales. En caso de que DBG ==0, incluso el compilador más tonto no tiene nada que analizar, por lo que no se genera código.
¿El compilador (gcc) optimizará declaraciones como if(DEBUG) {…} out, si en el código de producción la macro DEBUG está establecida en 0? Entiendo que hay buenas razones para dejar las declaraciones de depuración visibles para el compilador, pero queda un mal presentimiento. -Palmadita
– Pat
2 de febrero de 2010 a las 10:48
Ver también Error al definir una macro de stringising con __VA_ARGS__
– jww
25 de febrero de 2019 a las 5:40