c++ - salida - ¿Hay un cortocircuito lógico en el preprocesador C?
funcion preprocesador en c++ (4)
No hay una evaluación de las expresiones durante el preprocesamiento, entonces, ¿cómo puede cortocircuitarse?
Sí, hay evaluación de la expresión durante el preprocesamiento .
C11: 6.10.1 Inclusión condicional (p4):
Antes de la evaluación , las invocaciones de macro en la lista de tokens de preprocesamiento se convertirán en ...
En una nota a pie de página 166:
Debido a que la expresión constante de control se evalúa durante la fase de traducción 4 , todos los identificadores ...
Estas declaraciones atestiguan claramente que hay evaluación de la expresión en el preprocesamiento . La condición necesaria es que la expresión de control debe evaluar un valor entero.
Ahora el operador &&
y ||
obedecerá las reglas habituales de cortocircuito de la norma C como se indica en el documento GNU .
Ahora ejecute este programa con //
sin //
y vea el resultado para ver el comportamiento del cortocircuito:
#include<stdio.h>
#define macro1 1
//#define macro2 1
int main( void )
{
#if defined (macro1) && defined (macro2)
printf( "Hello!/n" );
#endif
printf("World/n");
return 0;
}
Los documentos de gcc para cpp explican sobre la directiva #if
:
[...] y operaciones lógicas (&& y ||). Los dos últimos obedecen las reglas habituales de cortocircuito de la norma C.
Qué significa eso? No hay una evaluación de las expresiones durante el preprocesamiento, entonces, ¿cómo puede cortocircuitarse?
A lo que se refieren es &&
y ||
operadores para #if
#if defined (AAA) || defined (BBB)
Si está defined (AAA)
está definido, entonces defined (BBB)
nunca se evalúa.
ACTUALIZAR
Así que la ejecución del cálculo será cortocircuitada. Por ejemplo, si -Wundef
con -Wundef
para advertir sobre el uso de macros no definidas.
#if defined FOO && FOO > 1000
#endif
#if FOO > 1000
#endif
resultará en
thomas:~ jeffery$ gcc foo.c -Wundef
foo.c:4:5: warning: ''FOO'' is not defined, evaluates to 0 [-Wundef]
#if FOO > 1000
^
1 warning generated.
Por lo tanto, la primera versión no genera la advertencia de macro no definida, porque FOO > 1000
no se evalúa.
MUSIONES VIEJAS
Esto es importante si la segunda parte es una macro que tiene efectos secundarios. La macro no se evaluaría, por lo que los efectos secundarios no tendrían lugar.
Para evitar el abuso de macro daré un ejemplo un tanto sano.
#define FOO
#define IF_WARN(x) _Pragma (#x) 1
#if defined(FOO) || IF_WARN(GCC warning "FOO not defined")
#endif
Ahora que construí este ejemplo, ahora tengo un problema. IF_WARN
siempre se evalúa.
eh, se necesita más investigación.
Bueno foo ... ahora que lo leí de nuevo.
Macros Todas las macros en la expresión se expanden antes de que comience el cálculo real del valor de la expresión.
La evaluación de las condiciones de macro es una parte (una parte importante) del preprocesamiento, por lo que se produce y el cortocircuito es significativo allí. Puedes ver ejemplos de las otras respuestas.
Un condicional es una directiva que le indica al preprocesador que seleccione si incluir o no una parte del código en la secuencia del token final que se pasa al compilador. Los condicionales del preprocesador pueden probar expresiones aritméticas, si un nombre se define como una macro, o ambos simultáneamente utilizando el operador especial definido. †
Además, puede reducir el tiempo de compilación. La modificación de las siguientes evaluaciones puede acelerar la compilación (depende de la implementación de un compilador).
Muy simple: las macros no definidas tienen un valor numérico cero, y la división por cero es ilegal.
#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif
#if
evalúa el resto de su línea como una expresión constante de entero. Su documentación vinculada comienza:
La directiva ''#if'' le permite probar el valor de una expresión aritmética, en lugar de la mera existencia de una macro.
Esa no es una extensión de gcc, la sintaxis de Standard para #if
es
#if
constant-expression new-line group
opt
.
El preprocesador C99 trata todas las constantes como [u]intmax_t
.