2009-10-13 40 views
18

Como dice la pregunta, ¿es capaz el preprocesador C de hacerlo?¿Puede el preprocesador C realizar operaciones aritméticas enteras?

ej .:

#define PI 3.1416 
#define OP PI/100 
#define OP2 PI%100 

¿Hay alguna manera OP y/u OP2 conseguir calculada en la fase de pre-procesamiento?

+4

PI no es un entero en el ejemplo; por lo tanto, ni OP ni OP2 serían enteros si el preprocesador se viera obligado a evaluarlos. Y los operandos de '%' no pueden ser números de coma flotante. –

Respuesta

25

¿Aritmética entera? Ejecutar el programa siguiente para averiguar:

#include "stdio.h" 
int main() { 
    #if 1 + 1 == 2 
     printf("1+1==2\n"); 
    #endif 
    #if 1 + 1 == 3 
     printf("1+1==3\n"); 
    #endif 
} 

respuesta es "sí", hay una manera de hacer que el preprocesador realizar aritmética de enteros, que es para usarlo en una condición preprocesador.

Sin embargo, observe que sus ejemplos no son aritméticos enteros. Acabo de verificar y el preprocesador de gcc falla si intentas hacer comparaciones flotantes. No he comprobado si el estándar permite alguna vez la aritmética de coma flotante en el preprocesador.

expansión de la macro regular no evalúa expresiones enteras, lo deja para el compilador, como puede verse por el procesamiento previo (-E en gcc) lo siguiente:

#define ONEPLUSONE (1 + 1) 
#if ONEPLUSONE == 2 
    int i = ONEPLUSONE; 
#endif 

El resultado es int i = (1 + 1); (más probablemente un poco de materia para indicar nombres de archivos de fuente y números de línea, etc.).

+6

Chris: Vivimos en el futuro ahora, y mientras los autos voladores siguen desaparecidos, ¡han llegado los valores de retorno predeterminados de la función principal! –

+11

@Chris: una llave estrecha, llegando a la cual "devuelve un valor de 0" (5.1.2.2.3, Terminación del programa). Si no puedo asumir el estándar C en una pregunta etiquetada como "C", entonces ¿a qué viene el mundo? ¿No puede encontrar a alguien que esté usando comentarios de estilo // en código que pueda ser visto por un compilador C89, y quejarse de ellos en su lugar? ;-) –

+0

@Chris - ¿El corsé de cierre? :-) –

13

El código que escribió en realidad no hace que el preprocesador haga ningún cálculo. Un #define hace el reemplazo de texto simple, así que con esto se define:

#define PI 3.1416 
#define OP PI/100 

este código:

if (OP == x) { ... } 

convierte

if (3.1416/100 == x) { ... } 

y luego se compila. El compilador a su vez puede optar por tomar una expresión tal y calcularla en tiempo de compilación y producir un código equivalente a esto:

if (0.031416 == x) { ... } 

Pero este es el compilador, no el preprocesador.

Para responder a su pregunta, sí, el preprocesador PUEDE hacer algo de aritmética. Esto se puede ver cuando se escribe algo como esto:

#if (3.141/100 == 20) 
    printf("yo"); 
#elif (3+3 == 6) 
    printf("hey"); 
#endif 
+3

Lamentablemente, si prueba su fragmento de compilación condicional, obtendrá el mensaje de GCC:' x.c: 5: 6: error: constante flotante en la expresión del preprocesador'. Puede hacer aritmética de enteros con el preprocesador C; no puedes hacer aritmética de coma flotante con él. –

+0

se ve como esquinas de corte gcc aquí, Stroustrup C++ 2da edición r.16.5 '#if constante-expresión',' r.5.19 expresión constante': ​​"... las constantes flotantes se deben convertir a tipos integrales". – denis

6

, quiero decir: que puede hacer aritmética :)

Como se demostró en 99 bottles of beer.

+0

¡Maravilloso ejemplo! :) – Avio

4

Sí.

No puedo creer que nadie haya vinculado a un ganador del concurso C ofuscado. El chico implementó una ALU en el preprocesador a través de recursive includes. Here es la implementación, y here es una especie de explicación.

Ahora, dicho esto, no quieres hacer lo que hizo ese tipo.Es divertido y todo, pero mira los tiempos de compilación en su archivo de pistas (sin mencionar el hecho de que el código resultante no se puede mantener). Más comúnmente, las personas usan el preprocesador estrictamente para el reemplazo de texto, y la evaluación de la aritmética de enteros constantes ocurre en tiempo de compilación o tiempo de ejecución.

Como otros señalaron sin embargo, puede hacer algo de aritmética en las sentencias #if.

+1

http://stackoverflow.com/questions/652788/what-is-the-worst-real-world-macros-pre-processor-abuse-youve-ever-come-across/1242177#1242177 - caos-pp . Abuso del preprocesador con estilo. –

6

Sí, se puede hacer con el preprocesador Boost. Y es compatible con C puro para que pueda usarlo en programas C con compilaciones solo en C. Sin embargo, su código involucra números flotantes, así que creo que eso debe hacerse de forma indirecta.

#include <boost/preprocessor/arithmetic/div.hpp> 
BOOST_PP_DIV(11, 5) // expands to 2 
#define KB 1024 
#define HKB BOOST_PP_DIV(A,2) 
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B))) 
#define RKB REM(KB,2) 

int div = HKB; 
int rem = RKB; 

Este preprocesa para (comprobar con -S gcc)

int div = 512; 
int rem = 0; 

Gracias a this thread.

Cuestiones relacionadas