C: Macros como funções com o while (0)

Palavras-chave: C, macro, multi-statement, cpp, pré-processador, preprocessor

Com alguma freqüência é necessário de definir macros com múltiplos comandos (statements) que possam ser usados de forma sintaticamente equivalente a chamadas de função. Nesse caso, não basta definir uma seqüência como:

#define foo(x) a1(x); a2(x)

Isso seria desastroso após um if, por exemplo. Tampouco adiantaria delimitar o bloco com chaves, o que não funcionaria numa situação como:

if (y) foo(z); else return;

Como, então, podemos definir tais macros? A resposta é: utilizando expressões “do {…} while(0)”, cuja utilidade em outras situações é bastante duvidosa. Veja o exemplo:

#define foo(x) do { a1(x); a2(x); } while (0)

Definindo macros dessa forma, cumprimos nosso objetivo: apesar da declaração aparentemente estranha, seu uso é equivalente a uma chamada de função em qualquer caso, incluindo loops e condicionais.

This entry was posted in C. Bookmark the permalink.

4 Responses to C: Macros como funções com o while (0)

  1. Felipe Lessa says:

    Seria legal dizer porque não é usado simplesmente um bloco, como em
    #define foo(x) { a1(x); a2(x); }

    Algo legal sobre isso: http://kernelnewbies.org/FAQ/DoWhile0

  2. Charles Kennedy says:

    Concordo com o Felipe, até porque eu costumava usar apenas
    #define foo(x) { a1(x); a2(x); }
    e nunca tive problemas. Se puder explicar ou tiver alguma fonte, ficaria grato.

    Off.: Estou gostando muito do blog. Vocês estão de parabéns.

  3. Charles Kennedy says:

    Quanto à fonte, a que o Felipe passou explica tudo. Mas ainda assim acho interessante explicar para quem não se vira no inglês.

  4. Claudio says:

    Expandindo if (y) foo(z); else return; com foo(x) definido como um bloco simples, temos:

    if (y) { … }; else return;

    o que não é uma construção válida em C. Basta fazer um teste:

    $ cat a.c
    #define foo(x) { a1(x); a2(x); }
    main(int y) { if (y) foo(y); else return; }

    $ gcc a.c
    a.c: In function ‘main’:
    a.c:2: error: expected expression before ‘else’

Leave a Reply

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