A saída deste código C é 49, mas alguém pode me explicar como? [duplicado]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Respostas
A macro transformará o código em:
printf("%d", (4+5 * 4+5 * 4+5));
que é efetivamente:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
Se você quiser cubo 9
para chegar 729
, você deve escrever CUBE((4+5))
.
Aqui está como a macro é expandida durante o processo de compilação:
printf("%d", (4+5 * 4+5 * 4+5));
Como *
tem uma precedência maior que +
, essa expressão é avaliada como (4 + (5 * 4) + (5 * 4) + 5)
, produzindo em 49
vez do esperado 729
.
Para evitar tais problemas de precedência do operador, todos os argumentos da macro devem estar entre parênteses na definição da macro, bem como na própria expressão:
#define CUBE(x) ((x) * (x) * (x))
Observe, entretanto, que essa expansão de CUBE
avalia x
várias vezes, o que é um problema se o argumento da macro tiver efeitos colaterais, como CUBE(i++)
.
Para evitar todos esses problemas, use uma função e deixe o compilador otimizá-la:
int cube(int x) {
return x * x * x;
}
Você pode adicionar static inline
antes desta definição de função, mas os otimizadores modernos ainda incorporarão a função sem isso.
O pré-processador C irá substituir literalmente todas as instâncias de x por 4 + 5, resultando no seguinte código:
i = 4+5*4+5*4+5;
(multiplicação primeiro, depois adição)
você precisa fornecer a entrada, como CUBE((4+5))
se deseja adicionar os números e enviar para CUBE
. Porque isso CUBE(4+5)
é basicamente expandido para uma 4+5*4+5*4+5
vez que coloca o todo 4+5
no lugar de x
. Portanto, 4+5*4+5*4+5
= 4+20+20+5
como a multiplicação vem primeiro e depois a adição deles dará 49
.
Defina a macro como #define CUBE(x) ((x)*(x)*(x))
se realmente procedesse primeiro a (4+5)
operação para cada (x)
e, em seguida, faça a *
operação.
Outra maneira é apenas usar CUBE((4+5))
ao chamar a macro, basicamente, primeiro adicionou os dois números e (4+5)
= 9
e depois fez CUBE(9)
, como:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
Leia Modern C , depois o esboço do padrão C n1570 e a documentação do GCC e do GDB e do CPP . Veja também este site de referência C.
Inspire-se em projetos de código aberto existentes, por exemplo, no github ou software GNU .
Com um compilador GCC recente , execute-o como gcc -Wall -Wextra -g
. Use também as -C -E
opções para obter o formulário pré-processado.
Você também pode se interessar pela extensão declaração-expr do GCC.
Seu CUBE(4+5)
é macro-expandiu-se para 4+5*4+5*4+5
o que é computado como 4+(5*4)+(5*4)+5
de acordo com a precedência de operadores C .
Considere codificar uma static inline
função como
static inline int cube(int x) { return x*x*x; }
ou se você precisa de uma macro, pelo menos
#define CUBE(X) ((X)*(X)*(X))
que não funcionará bem CUBE(i++)
(enquanto com a inline
função, cube(i++)
faz o que você quer: incrementar i
uma vez!).
BTW, você poderia usar GPP , ou GNU m4 , (ou seu próprio gerador, ou GNU bison ) para gerar algum código C. Como regra geral, pense com AST s: quando você gerar código C, emita muitos parênteses inúteis, como, por exemplo, em Chicken Scheme , SWIG , ou em CAIA ou em my manydl.c
Você também pode usar o analisador estático Clang em seu código (e talvez Frama-C ).
Você pode estar interessado em ler algumas diretrizes de codificação como as do MISRA C ou GNU .