C, C++: Cuidado com funções definidas como macros

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;
}
This entry was posted in C, CPP and tagged , , , , , . Bookmark the permalink.

8 Responses to C, C++: Cuidado com funções definidas como macros

  1. 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.

  2. eljunior says:

    por isso que o adequado é botar os códigos das macros entre parênteses:

    #define quadrado(n) ((n) * (n))

  3. 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.

  4. Esse negócio de funções por macro nunca deram muito certo.
    O que rola é usar inline mesmo.

  5. Coster says:

    É bom lembrar que inline é apenas um hint pro compilador, e que sua presença não garante que a função será “inlinezinada”.

Leave a Reply

Your email address will not be published. Required fields are marked *