La salida de este código C es 49, pero ¿alguien puede explicarme cómo? [duplicar]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Respuestas
Macro cambiará el código a:
printf("%d", (4+5 * 4+5 * 4+5));
que es efectivamente:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
Si desea 9
obtener un cubo 729
, debe escribir CUBE((4+5))
.
Así es como se expande la macro durante el proceso de compilación:
printf("%d", (4+5 * 4+5 * 4+5));
Dado que *
tiene una precedencia mayor que +
, esta expresión se evalúa como (4 + (5 * 4) + (5 * 4) + 5)
, produciendo en 49
lugar de lo esperado 729
.
Para evitar estos problemas de precedencia de operadores, todos los argumentos de macro deben estar entre paréntesis en la definición de macro, así como en la expresión en sí:
#define CUBE(x) ((x) * (x) * (x))
Sin embargo , tenga en cuenta que esta expansión de se CUBE
evalúa x
varias veces, lo cual es un problema si el argumento macro tiene efectos secundarios, como CUBE(i++)
.
Para evitar todos estos problemas, use una función y deje que el compilador la optimice:
int cube(int x) {
return x * x * x;
}
Puede agregar static inline
delante de esta definición de función, pero los optimizadores modernos seguirán incorporando la función sin esto.
El preprocesador de C sustituirá literalmente todas las instancias de x por 4 + 5, lo que dará como resultado el siguiente código:
i = 4+5*4+5*4+5;
(multiplicación primero, luego suma)
debe dar la entrada como CUBE((4+5))
si desea agregar los números y luego enviar a CUBE
. Porque CUBE(4+5)
básicamente se expande a 4+5*4+5*4+5
cuando coloca el todo 4+5
en el lugar de x
. Entonces, 4+5*4+5*4+5
= 4+20+20+5
ya que la multiplicación viene primero y luego sumarlos dará 49
.
Defina la macro como #define CUBE(x) ((x)*(x)*(x))
en realidad, primero proceda con la (4+5)
operación para todos (x)
y luego realice la *
operación.
Otra forma es usarlo CUBE((4+5))
mientras se llama a la macro, básicamente primero agregó los dos números y (4+5)
= 9
y luego lo hizo CUBE(9)
, como:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
Lea Modern C , luego el borrador del estándar C n1570 , y la documentación de GCC y de GDB y de CPP . Consulte también este sitio web de referencia de C.
Inspírate en proyectos de código abierto existentes, por ejemplo, en github o software GNU .
Con un compilador GCC reciente , invocalo como gcc -Wall -Wextra -g
. Utilice también las -C -E
opciones para obtener el formulario preprocesado.
También podría interesarle la extensión statement-expr de GCC.
Su CUBE(4+5)
es-macro expandido para 4+5*4+5*4+5
que se calcula como 4+(5*4)+(5*4)+5
de acuerdo con la precedencia de operadores C .
Considere codificar una static inline
función como
static inline int cube(int x) { return x*x*x; }
o si necesitas una macro, al menos
#define CUBE(X) ((X)*(X)*(X))
que no funcionará bien CUBE(i++)
(mientras que con la inline
función, cube(i++)
hace lo que quieres que haga: ¡incrementar i
una vez!).
Por cierto, puede usar GPP o GNU m4 (o su propio generador, o GNU bison ) para generar algo de código C. Como regla general, piense con AST s: cuando genera código C, emite muchos paréntesis inútiles, como por ejemplo en Chicken Scheme , SWIG o en CAIA o en my manydl.c
También puede usar el analizador estático Clang en su código (y tal vez Frama-C ).
Puede que le interese leer algunas pautas de codificación como MISRA C o GNU .