Desafio C

Include guard e macro MAX

Enunciado

Crie dois arquivos de cabeçalho: utils.h e main.c. O arquivo utils.h deve conter uma include guard e definir uma macro MAX(a,b) que retorna o maior entre dois valores. O arquivo main.c deve incluir utils.h duas vezes (para testar a guarda) e usar a macro MAX para imprimir o maior entre 10 e 20. Compile e execute.

Requisitos

  • utils.h deve ter include guard com #ifndef UTILS_H, #define UTILS_H e #endif.
  • utils.h deve definir a macro MAX(a,b) corretamente parentizada.
  • main.c deve incluir utils.h duas vezes.
  • O programa deve imprimir O maior e: 20.

Código inicial

// utils.h
#ifndef UTILS_H
#define UTILS_H

// Defina a macro MAX aqui

#endif

// main.c
#include <stdio.h>
#include "utils.h"
#include "utils.h" // segunda inclusão

int main(void) {
    // Use MAX e imprima
    return 0;
}

Saída esperada

O maior e: 20
Ver dica

A macro MAX deve ser algo como #define MAX(a,b) ((a) > (b) ? (a) : (b)). A include guard evita que o conteúdo seja duplicado.

Mostrar solução

utils.h

#ifndef UTILS_H
#define UTILS_H

// Macro que retorna o maior entre dois valores
#define MAX(a,b) ((a) > (b) ? (a) : (b))

#endif

main.c

#include <stdio.h>
#include "utils.h"
#include "utils.h" // segunda inclusão: a guarda impede duplicação

int main(void) {
    int x = 10, y = 20;
    printf("O maior e: %d\n", MAX(x, y));
    return 0;
}

Passo a passo

  1. Em utils.h, a diretiva #ifndef UTILS_H verifica se UTILS_H ainda não foi definida.
  2. Se não foi, #define UTILS_H define a macro de controle.
  3. Em seguida, definimos a macro MAX(a,b) com parênteses extras para garantir a precedência correta.
  4. #endif fecha o bloco condicional.
  5. Em main.c, incluímos utils.h duas vezes. Na primeira, UTILS_H é definida e o conteúdo é processado. Na segunda, #ifndef UTILS_H é falso, então o conteúdo é ignorado.
  6. Usamos MAX(x, y) dentro do printf. O pré-processador expande para ((x) > (y) ? (x) : (y)), que avalia para 20.

Por que funciona

A include guard garante que o conteúdo do cabeçalho seja incluído apenas uma vez por unidade de compilação. Sem ela, a segunda inclusão causaria redefinição da macro MAX, o que é um erro (ou aviso) em C. A macro MAX funciona para qualquer tipo comparável com >, desde que os parênteses preservem a ordem de avaliação.

Erros comuns

  • Esquecer o #endif: erro de pré-processamento.
  • Nome da guarda conflitante: usar #ifndef UTILS_H em outro arquivo pode causar conflito. Use nomes únicos, como UTILS_H.
  • Macro MAX sem parênteses: #define MAX(a,b) a > b ? a : b. Se usada em 2 * MAX(3,4), a expansão vira 2 * 3 > 4 ? 3 : 4, resultando em 6 > 4 ? 3 : 4 → 3, incorreto. Corrija com ((a) > (b) ? (a) : (b)).
  • Efeitos colaterais: MAX(i++, j) pode incrementar i duas vezes. Evite argumentos com efeitos colaterais.

Outra forma de resolver

Use uma função inline em vez de macro:

static inline int max_int(int a, int b) { return a > b ? a : b; }

Isso evita problemas de duplicação de argumentos e é mais seguro, mas não é genérico para todos os tipos.

Saída esperada

O maior e: 20