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 TRACING
me dirá que se definió el rastreo. -
#if TRACING
controla 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
TRACING
tiene un valor numérico (como en#define TRACING 2 /n)
, cpp tiene una expresión válida y no hemos cambiado el valor. - Si
TRACING
no 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
TRACING
tiene 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 untrue
valor. Los únicos tokens que hacen lo correcto son los literales booleanostrue
yfalse
.
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?