preprocessor - Prueba de definición de macro vacía
c-preprocessor (3)
Tengo un conjunto de macros de depuración en tracing.hh. Si genera código y la salida se controla mediante un indicador de macro en el código fuente real:
// File: foo.cc
#define TRACING 0
#include "tracing.hh"
// Away we go . . .
TRACEF("debug message");
La marca TRACING debe tener un valor; Normalmente alterno entre 0 y 1.
Dentro del rastreo.h,
-
#ifdef TRACINGme dirá que se definió el rastreo. -
#if TRACINGcontrola la definición de macros funcionales comoTRACEF()
Pero ¿y si TRACING no tiene valor? Entonces #if TRACING produce un error:
In file included from foo.c:3:
tracing.hh:73:12: error: #if with no expression
¿Cómo puedo probar si TRACING está definido pero no tiene valor?
Con la sugerencia de Matti y algo más de curiosidad, creo que el problema es el siguiente: si TRACING no tiene ningún valor, necesitamos una expresión de preprocesador válida en la prueba #if ... El manual de Gnu cpp dice que tiene que evaluar una expresión entera, por lo que necesitamos una expresión que sea válida incluso si falta uno de los argumentos. Lo que finalmente encontré es:
#if (TRACING + 0)
# . . .
- Si
TRACINGtiene un valor numérico (como en#define TRACING 2 /n), cpp tiene una expresión válida y no hemos cambiado el valor. - Si
TRACINGno tiene ningún valor (como en#define TRACING /n), el preprocesador evalúa#if (+0)comofalse
El único caso que este no maneja es
- Si
TRACINGtiene un valor de token ( es decir ,ON). El manual de cpp dice "Los identificadores que no son macros ... se consideran todos como el número cero " , que se evalúa comofalse. En este caso, sin embargo, tendría más sentido considerar esto como untruevalor. Los únicos tokens que hacen lo correcto son los literales booleanostrueyfalse.
Tarde a la fiesta, pero encontré un buen truco para distinguir -DTRACING=0 de -DTRACING :
#if (0-TRACING-1)==1 && (TRACING+0)!=-2
#error "tracing empty"
#endif
Si TRACING está vacío, la expresión se evalúa como 0--1 => 1 .
Si TRACING es 0, la expresión se evalúa como 0-0-1 => -1
Agregué un cheque adicional en el caso de TRACING==-2 que haría que la primera prueba pasara.
Esto no funciona para los literales de cuerdas, por supuesto.
haría
#if defined(TRACING) && !TRACING
¿Haz el truco?