2010-01-22 3 views
6

Este es un programa normal de rutina C que descubrí en un banco de preguntas. Se muestra a continuación:El uso de resultados de macro en resultados incorrectos cuando se usa como parte de una expresión matemática más grande, ¿por qué sucede esto?

#define CUBE(p) p*p*p 

main() 
{ 
    int k; 
    k = 27/CUBE(3); 
    printf("%d", k); 
} 

Según mi comprensión y el conocimiento del valor de K debe ser al menos 1 CUBO (3) sería reemplazado por 3 * 3 * 3 durante el procesamiento previo y después de la compilación posterior sería dar el valor de 1, pero en su lugar ha mostrado el valor de 81, lo que me ha hecho sentir curiosidad por saber cómo sucedió.

¿Alguien puede justificar la respuesta del 81 a esta pregunta anterior.

+0

Simplemente reemplace 'CUBE (3)' en su línea 'k = ...' por '3 * 3 * 3' y verá cuál es su expresión. –

+2

¿Qué idioma es el que hace que las "dudas" parezcan sinónimos de "problema" o "pregunta"? – Ether

+2

@Ether: Como indio, definitivamente puedo decir que somos nosotros. ¡Aprendí de la manera difícil yo mismo! Una vez, mi profesor me dijo: "¿Tiene alguna duda sobre la pregunta o sobre la pregunta?" Espero que no dudes de mí cuando digo eso. :-) –

Respuesta

3

Preprocesadores debe paréntesis correctamente. Reemplácelo por

#define CUBE(p) ((p)*(p)*(p)) 

y vea.

+2

Y tenga cuidado, incluso esto está roto para CUBO (++ i) o CUBO (f (x)) –

+0

que sería UB –

15

El preprocesador se limita a sustituir

CUBE(3) 

con

3*3*3 

por lo que terminan con:

k=27/3*3*3 

cual, evaluados de izquierda a derecha con la prioridad de los operadores, se encuentra en hecho 81.

Si se agrega parenthesees alrededor de la macro, debe encontrar los resultados son correctos:

#define CUBE(p) (p*p*p) 

sería aún mejor para rodear cada instancia de p con parenthesees así, como en:

#define CUBE(p) ((p)*(p)*(p)) 

Lo que le permitirá pasar expresiones a la macro correctamente (por ejemplo, 1 + 2).

+1

O, mejor, '#define CUBE (p) ((p) * (p) * (p))' –

+0

De hecho lo haría: #define CUBE (p) ((p) * (p) * (p)) Pero incluso eso es malo, si p es una llamada a función. Inadvertidamente puede ser llamado 3 veces. –

+0

wow ... Eso es el juego de la precedencia del operador. Gracias James y Alok. – maddy

0
 #define CUBE(p) p*p*p 
    main() 
    { 
     int k; 
     k=27/CUBE(3); 
     printf("%d",k); 

    } 

Según mi comprensión y el conocimiento del valor de K debe ser al menos 1 CUBO (3) sería reemplazado por 3 * 3 * 3 en la decodificación previa

y después de la compilación posterior estaría dando el valor de 1, pero en su lugar ha mostrado el valor de 81, lo que me ha hecho sentir curiosidad por saber cómo sucedió.

NO,

k= 27/3*3*3 

=(((27/3)*3)*3) (The precedence of `*` and `/` are same but the associativity is from left to right) 
=((9*3)*3) =81 

Reemplazar #define CUBE(p) p*p*p con #define CUBE(p) ((p)*(p)*(p))

+0

Muchas gracias a todos – maddy

1

Su macro no está protegida.Trate

#define CUBE(p) ((p)*(p)*(p)) 

La macro actual se amplió para

k=27/3*3*3 

que es ((27/3) * 3) * 3

0
k=27/CUBE(3); => k=27/3 * 3 * 3; 

lo ves? CUBE debería definirse así en su lugar:

#define CUBE(p) ((p)*(p)*(p)) 
0

Cuando hace macros, debe tener cuidado con la forma de colocar paréntesis. En este caso, no tiene ninguno, por lo que la expresión se convierte en 27/3 * 3 * 3, que por las reglas de precedencia de/y * se convierte en (27/3) * 3 * 3.

2

Las macros C realizan una sustitución de texto (es decir, es equivalente a copiar y pegar código). Así que el código va desde:

k=27/CUBE(3); 

a

k=27/3*3*3; 

división y multiplicación tienen la misma prioridad y han de izquierda a derecha asociatividad, por lo que este se analiza como:

k=((27/3)*3)*3; 

que es 9 * 3 * 3 = 81.

Es por eso que las macros C siempre deben definirse con el uso liberal de paren tesis:

#define CUBE(p) ((p) * (p) * (p)) 

Para obtener más información, consulte http://c-faq.com/cpp/safemacros.html del FAQ comp.lang.c.

2

Debido a que las macros son una sustitución textual, que se resuelve a:

k = 27/3 * 3 * 3; 

Desde la multiplicación y división suceden de izquierda a derecha, que se resuelve a:

k = ((27/3) * 3) * 3; 

Por lo tanto, desea cambiar eso de dos maneras:

#define CUBE(p) ((p)*(p)*(p)) 

Los paréntesis externos hacen que las multiplicaciones sean d uno antes de cualquier otra operación.

Los paréntesis alrededor del p del individuo son para el caso en el que hacer:

CUBE(1 + 2); 

Sin esos paréntesis interiores, precedencia de los operadores lo tropezará.

0

Ambos/y * operadores tienen la misma precedencia. Para ejecutar 3 * 3 * 3 primero, deberías encerrarlos entre paréntesis.

#include <stdio.h> 

#define CUBE(p) p*p*p 

int 
main() 
{ 
    int k; 
    k=27/(CUBE(3)); 
    printf("%d",k); 
    return 0; 
} 
4

Debido a la precedencia de operadores 27/3*3*3 = 81

Usted podría utilizar en su lugar:

inline int cube(int p) { return p*p*p; } 
0

su la forma en que se implementa la asociatividad y precedencia de los operadores. cuando la expresión se expande se convierte en 27/3 * 3 * 3 y no 27/(3 * 3 * 3) ahora, la división y la multiplicación tienen la misma precedencia en C pero la asociatividad es de izquierda a derecha para ambos. por lo que se puede mostrar como: (27/3) * 3 * 3 que a su vez es igual a (9 * 3) * 3 = 81 también, si recuerda la antigua regla aritmética de BODMAS (División de multiplicación adicional Resta), este es el orden de precedencia, luego hacemos división primero y luego multiplicación. así que de nuevo obtenemos la respuesta como 81 para 27/3 * 3 * 3.

0

Hola respuesta para esto es: 81 Explicación: En la etapa k = 27/cubo (3) cubo (3) se sustituye por 3 * 3 * 3 por preprocessor.then anterior afirmación se vuelve tan k = 27/3 * 3 * 3 en que la expresión 27/3 es evaluada por el compilador c (precedencia del operador) el resultado es (27/3): 9 la declaración k = 27/3 * 3 * 3 se convierte en k = 9 * 3 * 3; el resultado para la instrucción anterior es 81:

Cuestiones relacionadas