sirve - file c++
¿Por qué el preprocesador C considera los valores de enumeración como iguales? (7)
Como decían las otras respuestas, el preprocesador C no ve enumeraciones. Espera, y solo puede entender, macros.
Según el estándar C99 , §6.10.1 (inclusión condicional):
Después de que se hayan realizado todos los reemplazos debido a la expansión de macro y el operador unario definido, todos los identificadores restantes se reemplazan con el número pp 0
En otras palabras, en una directiva #if o #elif, las macros que no se pueden expandir, porque no existen / no están definidas, se comportarán exactamente como si se hubieran definido como 0 y, por lo tanto, siempre serán iguales a El uno al otro.
Puede detectar comportamientos no deseados como este en GCC / clang con la opción de advertencia -Wundef (probablemente querrá hacerlo fatal con -Werror = undef).
¿Por qué se ejecuta la línea
std::cout
en el siguiente código aunque
A
y
B
son diferentes?
#include <iostream>
enum T { A = 1, B = 2 };
// #define A 1
// #define B 2
int main() {
#if (A == B)
std::cout << A << B;
#endif
}
Si uso
#define
lugar (como se comentó), no obtengo ningún resultado como esperaba.
Motivo de la pregunta:
Quiero tener un selector de modo para algún código de prueba en el que pueda cambiar fácilmente los modos comentando / descomentando líneas en la parte superior:
enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
// #define MODE MODE_RGB
#define MODE MODE_GREY
// #define MODE MODE_CMYK
int main() {
#if (MODE == MODE_RGB)
// do RGB stuff
#elif (MODE == MODE_GREY)
// do greyscale stuff
#else
// do CMYK stuff
#endif
// some common code
some_function(arg1, arg2,
#if (MODE == MODE_RGB)
// RGB calculation for arg3,
#elif (MODE == MODE_GREY)
// greyscale calculation for arg3,
#else
// CMYK calculation for arg3,
#endif
arg4, arg5);
}
Sé que puedo usar valores numéricos, por ejemplo
#define MODE 1 // RGB
...
#if (MODE == 1) // RGB
pero hace que el código sea menos legible.
¿Hay una solución elegante para esto?
El preprocesador se ejecuta antes que el compilador, lo que significa que el preprocesador no sabe nada sobre los símbolos definidos por el compilador y, por lo tanto, no puede actuar dependiendo de ellos.
Esto se debe a que el preprocesador funciona antes del tiempo de compilación.
Como las definiciones de enumeración se producen en el momento de la compilación, A y B se definirán como vacías (número de pp
0
), y por lo tanto iguales, en el tiempo de preprocesamiento, y por lo tanto la declaración de salida se incluye en el código compilado.
Cuando usa
#define
, se definen de manera diferente en el tiempo de procesamiento previo y, por lo tanto, la declaración se evalúa como falsa.
En relación con su comentario sobre lo que desea hacer, no necesita usar el preprocesador
#if
para hacerlo.
Puede usar el estándar
if
MODE
y
MODE_GREY
(o
MODE_RGB
o
MODE_CMYK
) todavía están definidos:
#include <iostream>
enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
#define MODE MODE_GREY
int main()
{
if( MODE == MODE_GREY )
std::cout << "Grey mode" << std::endl;
else if( MODE == MODE_RGB )
std::cout << "RGB mode" << std::endl;
else if( MODE == MODE_CMYK )
std::cout << "CMYK mode" << std::endl;
return 0;
}
La otra opción que usa solo el preprocesador es hacer esto como @TripeHound respondió correctamente a continuación .
Las publicaciones explican por qué, pero una posible solución para usted que mantiene la legibilidad podría ser así
#define MODE_RGB
int main()
{
#ifdef MODE_RGB
std::cout << "RGB mode" << std::endl;
#elif defined MODE_GREY
std::cout << "Grey mode" << std::endl;
#elif defined MODE_CMYK
std::cout << "CMYK mode" << std::endl;
#endif
}
Solo necesita cambiar la macro en la parte superior, solo se define la macro que le interesa.
También puede incluir una verificación para asegurarse de que uno y solo uno esté definido y, si no, y hacer
#error "You must define MODE_RGB, MODE_GREY or MODE_CMYK
Los identificadores que no son macros definidos se interpretan como valor 0 en las directivas de preprocesador condicional.
Por lo tanto, dado que no había definido las macros
A
y
B
, ambas se consideran 0 y dos 0 son iguales entre sí.
La razón por la cual los identificadores indefinidos (para el preprocesador) se consideran 0 es porque permite usar macros indefinidas en el condicional sin usar
#ifdef
.
No hay macros llamadas
A
o
B
, por lo que en su línea
#if
,
A
y
B
se reemplazan por
0
, por lo que en realidad tiene:
enum T { A = 1, B = 2 };
int main() {
#if (0 == 0)
std::cout << A << B;
#endif
}
El preprocesador se ejecuta antes de que el compilador sepa algo sobre su
enum
.
El preprocesador solo conoce las macros (
#define
).
Otras respuestas explican por qué lo que estás intentando no funciona; para una alternativa, probablemente iría con:
#define RGB 1
#define GREY 2
#define CMYK 3
#define MODE RGB
#if MODE == RGB
//RGB-mode code
#elif MODE == GREY
//Greyscale code
#elif MODE == CMYK
//CMYK code
#else
# error Undefined MODE
#endif
Es posible que desee prefijos en RGB / GREY / CMYK si existe el peligro de conflictos con el código fuente "real".