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
?
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
?
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.
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. –
@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 –
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))
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.
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'. –
@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 –
Probar:
#define square(x) ((x)*(x))
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))
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'. –
He reparado la macro definida incorrectamente. Se agregó otro conjunto de paréntesis adjuntos. – don
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 ... –
@ 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. –
Dicho esto, hay, por supuesto, más malos usos que los buenos :) –