Menu

Macros em C: #define, macros com argumentos e as regras dos parênteses

Macros do tipo objeto e do tipo função com #define - por que cada argumento e o corpo inteiro precisam de parênteses, a armadilha da avaliação múltipla, macros de várias linhas com do-while(0) e quando uma função ou um const é a ferramenta melhor.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Uma macro é um nome que o pré-processador substitui por algum texto antes de o compilador rodar. Esse é o mecanismo inteiro, e toda regra desta página é uma consequência dele: macros não têm tipos, não respeitam escopo, não avaliam argumentos e não sabem o que é uma chamada de função. Elas copiam texto.

Usadas com cuidado, são indispensáveis - chaves de portabilidade, macros de asserção que capturam o número da linha, constantes de tempo de compilação que funcionam em tamanhos de array. Usadas sem cuidado, produzem bugs que parecem impossíveis até você expandir o arquivo.

Macros do tipo objeto

A forma mais simples define um nome que representa um valor:

Por convenção, esses nomes ficam em UPPER_SNAKE_CASE para que o leitor perceba num relance que um símbolo é uma macro e não uma variável. Essa convenção importa mais do que o normal aqui, porque macros ignoram escopo: um #define dentro de uma função continua valendo para o resto do arquivo, e ele reescreverá alegremente uma variável de mesmo nome em outra função.

#undef NOME remove uma definição, então um nome pode ser redefinido depois sem um aviso de redefinição.

Macros do tipo função

Coloque uma lista de parâmetros logo depois do nome - sem espaço antes do parêntese de abertura - e a macro passa a receber argumentos:

A regra do espaço é real: #define SQUARE (x) ((x)*(x)) define uma macro do tipo objeto chamada SQUARE cujo texto de substituição começa com (x). O erro de compilação que vem em seguida não vai mencionar espaçamento.

As regras dos parênteses

São duas, e ambas existem porque o corpo é colado em uma expressão que você não enxerga ao escrever a macro.

Regra 1: coloque cada parâmetro entre parênteses. Sem isso, um argumento que seja ele próprio uma expressão é despedaçado pela precedência:

#define SQUARE_BAD(x) x * x

SQUARE_BAD(2 + 3)   /* vira 2 + 3 * 2 + 3  ==  11, não 25 */

Regra 2: coloque o corpo inteiro entre parênteses. Sem isso, a expressão ao redor despedaça o resultado:

#define DOUBLE_BAD(x) (x) + (x)

10 / DOUBLE_BAD(5)  /* vira 10 / (5) + (5)  ==  7, não 1 */

Rode as duas falhas lado a lado com suas versões corrigidas:

As duas versões ruins compilam sem um único aviso e produzem números errados. O hábito a construir é mecânico: envolva cada parâmetro, depois envolva o resultado. ((a) > (b) ? (a) : (b)) parece barulhento, e o barulho é o ponto.

A armadilha da avaliação múltipla

Parênteses não te salvam do segundo perigo. Uma macro cola o texto do argumento em cada lugar onde o parâmetro aparece, então um argumento com efeito colateral acontece mais de uma vez:

A macro expande para ((i++) > (j) ? (i++) : (j)). A comparação incrementa i para 6 e compara 5 com 3; o ramo verdadeiro incrementa i de novo para 7 e devolve 6. Então m é 6 e i é 7 - nenhum dos dois é o que "o maior entre i e j" deveria dar. Uma função max(i++, j) estaria correta, porque o argumento é avaliado uma única vez antes da chamada.

A mesma armadilha pega qualquer coisa com efeito colateral: SQUARE(rand()) chama rand() duas vezes e multiplica dois números diferentes. CHECK(read_byte()) consome dois bytes.

Duas defesas, em ordem de preferência:

  1. Use uma função de verdade. Se você precisar dela para vários tipos, escreva uma por tipo, ou use uma função static inline em um cabeçalho.
  2. Se tiver mesmo que ser uma macro, documente bem alto que os argumentos são avaliados mais de uma vez, e mantenha os pontos de chamada livres de efeitos colaterais.

Macros de várias linhas e o do-while(0)

O corpo de uma macro pode ocupar várias linhas se cada linha exceto a última terminar com uma barra invertida. A versão ingênua parece boa:

#define LOG_TWICE(msg) \
    printf("%s\n", msg); \
    printf("%s\n", msg)

E então ela quebra, silenciosamente, no único lugar onde isso importa:

if (verbose)
    LOG_TWICE("hello");
else
    printf("quiet\n");

Depois da substituição, o if é dono apenas do primeiro printf, o segundo executa incondicionalmente, e o else agora não tem um if correspondente - um erro de compilação cuja mensagem não aponta para nada útil. Envolver o corpo em chaves simples não melhora: o ; depois de LOG_TWICE("hello") vira um comando vazio que termina o if, e o else quebra de novo.

O idioma que funciona é do { ... } while (0):

do { ... } while (0) é um único comando, executa seu corpo exatamente uma vez e exige um ponto e vírgula depois dele - então o ponto de chamada se lê como uma chamada de função comum e se comporta como uma em qualquer contexto de controle de fluxo. Cuidado com as barras invertidas: um espaço perdido depois de uma barra encerra a continuação e produz um erro desconcertante.

Macros predefinidas e padrões de asserção

O pré-processador define várias macros por conta própria, e elas são a razão pela qual algumas coisas simplesmente não podem ser funções:

__FILE__ e __LINE__ expandem onde estão escritos, então colocá-los dentro de uma macro captura a posição de quem chamou. Uma função não conseguiria fazer isso - dentro de uma função eles sempre relatariam o arquivo e a linha da própria função de log. É exatamente assim que a macro assert padrão informa a localização da expressão que falhou.

Outros nomes predefinidos úteis: __DATE__, __TIME__ e __STDC_VERSION__ (por exemplo 201710L para C17).

Dois operadores que vale conhecer

Dentro do corpo de uma macro, # transforma um parâmetro em uma literal de string ("stringização") e ## cola tokens ("colagem de tokens").

SHOW(width * height) vira printf("width * height" " = %d\n", (width * height)); - literais de string adjacentes são unidas pelo compilador, então uma chamada imprime tanto o texto da expressão quanto seu valor. É um truque de depuração que vale lembrar.

## é mais raro e aparece principalmente em macros de geração de código: #define MAKE_VAR(n) int var_##n transforma MAKE_VAR(3) em int var_3. Use com parcimônia; identificadores construídos pelo pré-processador não podem ser buscados por nome, o que torna o código difícil de navegar.

Macros versus funções versus const

Use a ferramenta mais fraca que resolve o problema:

  • variável const - const double PI = 3.14159; tem tipo, obedece a escopo, aparece no depurador e não pode ser redefinida por um cabeçalho não relacionado. Prefira isso para valores usados em tempo de execução.
  • enum - enum { MAX_USERS = 100 }; dá uma constante inteira nomeada que funciona onde o C exige uma constante de tempo de compilação, com tipo e escopo. Boa para limites inteiros.
  • função static inline - tem os tipos verificados, avalia cada argumento exatamente uma vez, e compiladores modernos a inserem inline exatamente como uma macro faria. Esta é a substituição certa para quase toda macro do tipo função.
  • Macro - quando você precisa de __LINE__, quando a coisa tem que funcionar antes de os tipos existirem (tamanhos de array em código mais antigo), quando você está chaveando código com compilação condicional, ou quando está gerando código repetitivo.

Um lugar onde as macros continuam imbatíveis é o dimensionamento de arrays, porque o resultado tem que ser uma constante de tempo de compilação:

Esta tem uma ressalva conhecida própria: ela só é correta para um array genuíno. Passe um ponteiro - que é no que um array se transforma ao ser entregue a uma função - e o sizeof mede o ponteiro, dando uma resposta errada e confiantemente silenciosa.

Depurando uma macro

Quando uma macro se comporta mal, não fique encarando. Expanda-a:

gcc -E program.c | tail -30

O texto substituído te diz na hora se o problema é um parêntese faltando, uma avaliação dupla ou um nome colidindo com outra coisa. Compile com -Wall -Wextra também - GCC e clang acrescentam notas de "in expansion of macro" que conectam a linha do erro relatado de volta à definição.

A seguir: arquivos de cabeçalho, onde #define e #include se combinam para deixar um projeto se espalhar por muitos arquivos-fonte sem colar as mesmas declarações duas vezes.

Perguntas frequentes

O que é uma macro em C?

Um trecho de texto nomeado que o pré-processador substitui no seu código-fonte antes da compilação. #define MAX 100 faz cada MAX posterior virar 100; #define SQUARE(x) ((x) * (x)) recebe argumentos e os substitui em um padrão. Macros não têm tipos e não obedecem a regras de escopo - são substituição de texto.

Por que macros em C precisam de tantos parênteses?

Porque o corpo é colado no código ao redor e só então analisado como um todo. #define SQUARE(x) x * x transforma SQUARE(2 + 3) em 2 + 3 * 2 + 3, que dá 11 em vez de 25. Envolver cada argumento e o corpo inteiro - ((x) * (x)) - faz o texto substituído agrupar do jeito que você pretendia, independentemente do que estiver em volta.

Qual é a diferença entre uma macro e uma função em C?

Uma função é compilada uma vez, tem os tipos verificados e avalia cada argumento exatamente uma vez. Uma macro é colada em cada uso, não verifica nada e pode avaliar um argumento várias vezes - então MAX(i++, j) pode incrementar i duas vezes. Prefira funções (e const/enum para constantes); use macros para o que funções não conseguem fazer, como capturar __LINE__ ou gerar código.

Por que uma macro de várias linhas é envolvida em do { ... } while (0)?

Para que ela se comporte como um único comando. Um corpo com chaves nuas quebra quando é seguido por um ponto e vírgula dentro de um if/else (o ponto e vírgula encerra o if cedo demais), e uma sequência simples de comandos quebra em um if sem chaves. do { ... } while (0) é um único comando que aceita um ponto e vírgula no fim e executa seu corpo exatamente uma vez.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR