2011-04-27 13 views
9

que estoy aprendiendo C, pero no entiendo esto:preprocesadores C y orden de las operaciones

#define square(x) x*x 
a = square(2+3) //a = 11 

Cuando esto se ejecuta, ¿por qué a terminan siendo 11?

+10

Del mismo modo que un consejo, este ejemplo muestra una de las muchas razones por las que usted debe evitar el uso de macros en C hasta que llegue el día en el que * * realmente ** sabes lo que estás haciendo. Por supuesto, cuando llegue ese día, sabrá por qué evitarlos en detalle ... –

+0

@ T.E.D .: Las macros (y el preprocesador en general) son una herramienta como cualquier otra. Este ejemplo no muestra por qué no debe usar macros en general; solo muestra un caso de uso particular para el cual no es apropiado aplicarlos. Hay usos buenos y malos de macros. –

+2

Dicho esto, hay, por supuesto, más malos usos que los buenos :) –

Respuesta

21

Se expande a 2+3*2+3, que es equivalente a 2+(3*2)+3. Utilice paréntesis para solucionarlo:

#define square(x) ((x)*(x)) 

Ahora intentarlo con square(x++) y se encontrará con más problemas de comportamiento (no definido). Evita hacer esto como una macro si puedes.

+3

La función C++ equivalente debería ser tan eficiente como una macro (en compiladores modernos con optimizaciones activadas) y no sufrirá de esto problema. –

+2

@Martin: Correcto, si el OP está usando C++. Las indicaciones indican que probablemente sea C. Creo que C99 también tiene funciones en línea, y parece que son una extensión en GNU C. Gracias por la sugerencia, usaré http://en.wikipedia.org/wiki/Inline_function#Language_support –

12

square(2+3) expande a 2+3*2+3 lo que equivale a 2+(3*2)+3 [* tiene mayor precedencia que +]

En gcc puede utilizar -E opción de ver lo que genera el preprocesador

C:\Users\SUPER USER>type a.c 
#define square(x) x*x 

int main() 
{ 
    a = square(2+3); //a = 11 
} 

C:\Users\SUPER USER>gcc -E a.c 
# 1 "a.c" 
# 1 "<built-in>" 
# 1 "<command-line>" 
# 1 "a.c" 


int main() 
{ 
    a = 2+3*2+3; 
} 

Remedio

Pruebe esto

#define square(x) ((x)*(x)) 
+0

-E :) – jhon

+0

+1 no solo para encontrar el problema sino también para enseñarle al OP (y al resto de nosotros) cómo solucionar estos problemas. – Heinzi

1

Debido 2 + 3 se sustituye literalmente en la expresión x * x, se hace 2 + 3 * 2 + 3, y el operador * tiene una prioridad más alta para que no se obtiene el resultado esperado.

encierran siempre argumentos macro y toda la expresión entre paréntesis para evitar esto:

#define SQUARE(x) ((x) * (x)) 

También tenga en cuenta que cualquier expresión que pase será evaluado dos veces, y que puede ser no deseado si la expresión tiene un efecto secundario tales como una tarea o una llamada de función. En estos casos, es mejor usar una función en línea.

+2

Encierre siempre las macros entre paréntesis. Con su sugerencia, '1.0/square (x)' se evaluaría a '1.0/(2 + 3) * (2 + 3)', por lo tanto '1.0' en lugar de' 0.04'. –

+0

@Sam: punto tomado. Irónico, pero yo mismo lo he dicho hace unos meses en esta respuesta: http://stackoverflow.com/questions/4455307/weird-macro-definition-issue/4455354#4455354 –

1

Probar:

#define square(x) ((x)*(x)) 
0

pensar en lo que se obtiene cuando se expande la macro. El preprocesador c ampliará esto como

a = 2 + 3 * 2 + 3 

Debe definir correctamente su macro. Encierre siempre la variable de macro entre paréntesis. Esto te daría el resultado esperado.

#define square(x) ((x)*(x)) 

La expansión de la macro sería la siguiente:

a = ((2 + 3) * (2 + 3)) 
+0

Su consejo no es "definir correctamente" la macro . '1.0/square (x)' se evaluaría a '1.0/(2 + 3) * (2 + 3)', por lo tanto '1.0' en lugar de' 0.04'. –

+0

He reparado la macro definida incorrectamente. Se agregó otro conjunto de paréntesis adjuntos. – don

Cuestiones relacionadas