Imagine uma função definida em uma macro que faça a potência de dois de um determinado número. Ela poderia ser definida da seguinte forma:
#define quadrado(n) \ n * n
Acontece que o comportamento, dependendo dos parâmetros, nem sempre é o esperado. Veja o que acontece no exemplo a seguir:
int main(void) { int a = 2; printf("%d\n", quadrado(a)); // Imprime 4 printf("%d\n", quadrado(a + 1)); // Imprime 5 return 0; }
A expansão da macro quadrado(a + 1), resultou a seguinte expressão:
a + 1 * a + 1 2 + 1 * 2 + 1 // Substituindo os valores de a 2 + 2 + 1 // Obedecendo a precedência dos operadores 5
Neste caso, para resolver o problema a sugestão seria usar uma função inline, que assim como a macro, poupa uma chamada de função mas se comporta como uma função convencional.
inline int quadrado(int n) { return n * n; }
Isso se deve ao fato das macros em C serem “meras” substituições textuais.
Agora, alguns compiladores, como o gcc, otimizam as funções de forma a usar inline sempre que possivel. Vc pode observar compilando 2 arquivos com as mesmas funções e um deles usando inline explicito – geram codigo executavel igual (mesmo tamanho, md5, etc). Agora o g++ gera codigo diferente sim.
por isso que o adequado é botar os códigos das macros entre parênteses:
#define quadrado(n) ((n) * (n))
Não resolveria completamente o problema, caso a função fosse chamada como: quadrado(n–). Neste caso, n seria decrementado duas vezes.
Pois é ;-)
Como foi bem escrito pelo kernel hacker “Rusty” Russel em seu post “Valid Uses of Macros”, elas tem alguma função, mas em geral é bem menor do que a maioria dos usuários costuma pensar.
Uma função como a do exemplo deveria ser “static inline”. Isto evitaria todos os problemas citados anteriormente, como avaliação parcial e reavaliação dos argumentos.
http://ozlabs.org/~rusty/index.cgi/tech/2009-03-13.html faltou o link pro post do Rusty.
Esse negócio de funções por macro nunca deram muito certo.
O que rola é usar inline mesmo.
É bom lembrar que inline é apenas um hint pro compilador, e que sua presença não garante que a função será “inlinezinada”.