Comparación de macros de directiva if


25

¿Por qué se #ifcumple la condición en el siguiente código?

#include <iostream>
#define VALUE foo    

int main() {    
#if VALUE == bar
    std::cout << "WORKS!" << std::endl;
#endif // VALUE
}

Respuestas:


26

La página en cppreference.com dice:

Después de toda expansión y evaluación macro de expresiones definidas y __has_include (desde C ++ 17), cualquier identificador que no sea un literal booleano se reemplaza con el número 0 (esto incluye identificadores que son palabras clave léxicamente, pero no tokens alternativos como y )

Entonces ambos fooy barson reemplazados por 0.


¿Qué pasa con C ++ 98, C ++ 03, C ++ 11 y C ++ 14?
— kelalaka

1
@kelalaka Es todo lo mismo. Ha sido así desde C89.
— SS Anne

1
@kelalaka El "desde C ++ 17" solo se refiere a la parte "y __has_include". Antes de C ++ 17 era lo mismo, solo con esa parte omitida.
— BessieTheCow

15

En una #ifdeclaración, cualquier identificador que permanezca después de la sustitución de macro (excepto para truey false) se reemplaza con la constante 0. Entonces su directiva se convierte

#if 0 == 0

cual es verdad.


Para aclarar, '#define VALUE foo' define el símbolo 'VALUE' para resolver al mismo valor que el símbolo 'foo', pero el símbolo 'foo' no tiene significado, por lo que se interpretará como 0.
— ManicDee

14

Esto se debe a que fooni barse les ha dado ninguna definición o valor, por lo que son iguales (es decir, reemplazados por un valor "0"). Los compiladores darán advertencias sobre esto.

El MSVCcompilador (Visual Studio 2019) ofrece lo siguiente:

advertencia C4668: 'foo' no se define como una macro de preprocesador, reemplazando con '0' para '# if / # elif'
advertencia C4668: 'bar' no se define como una macro de preprocesador, reemplazando con '0' para '#if / # elif '

Por VALUElo tanto, se le da el valor '0' (predeterminado para foo) y bartambién tiene '0', por lo que se VALUE == barevalúa como "VERDADERO".

Del mismo modo, clang-clda lo siguiente:

advertencia: 'foo' no está definido, se evalúa a 0 [-Wundef]
advertencia: 'barra' no está definido, se evalúa a 0 [-Wundef]


¿La advertencia es obligatoria o es una característica de los compiladores?
— kelalaka

1
@kelalaka Hasta donde sé, ¡no son obligatorias las "advertencias" del compilador! Incluso con los compiladores MSVCy clang-cl, esta advertencia se puede deshabilitar (ya sea específicamente o estableciendo un 'nivel' de advertencia apropiado).
— Adrian Mole

0

Para lograr lo que busca, intente esto:

#include <iostream>
#define DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

En este caso, puede desactivar las declaraciones de depuración cambiando "define" a "undef".

#include <iostream>
#undef DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

Es posible que su compilador le permita definir DEPURACIÓN fuera del código, en cuyo punto puede reducir el código a

#include <iostream>

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

Y luego invoque el compilador con una opción como -DDEBUG = 0

Consulte el capítulo sobre Programación defensiva en Steve McConnell, "Código completo".

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.