Include guard

Origem: Wikipédia, a enciclopédia livre.

Nas linguagens de programação C e C++, uma include guard, às vezes chamada de macro guard ou header guard, é uma construção usada para evitar o problema da dupla inclusão ao lidar com a diretiva "include". A adição de #include guards em um arquivo cabeçalho é uma forma de tornar esse arquivo idempotente.

Dupla inclusão[editar | editar código-fonte]

O seguinte código em C demonstra um problema real que pode surgir se #include guards estão faltando:

Arquivo "avo.h"
struct foo {
    int member;
};
Arquivo "mae.h"
#include "avo.h"
Arquivo "crianca.c"
#include "avo.h"
#include "mae.h"

Aqui, o arquivo "crianca.c" incluiu indiretamente duas cópias do texto no arquivo cabeçalho "avo.h". Isto provoca um erro de compilação, já que a estrutura do tipo foo vai acabar sendo definida duas vezes. Em C++, isso seria uma violação da One Definition Rule (ou "regra da definição única," em tradução livre).

Uso de #include guards[editar | editar código-fonte]

Agora considere os seguintes arquivos:

Arquivo "avo.h"
#ifndef AVO_H
#define AVO_H

struct foo {
    int member;
};

#endif /* AVO_H */
Arquivo "mae.h"
#include "avo.h"
Arquivo "crianca.c"
#include "avo.h"
#include "mae.h"

Aqui, a primeira inclusão de "avo.h" faz com que a macro AVO_H seja definida. Em seguida, quando "crianca.c" inclui "avo.h" pela segunda vez, o teste do #ifndef retorna falso, e o pré-processador salta para baixo até o #endif, evitando, assim, a segunda definição de structfoo. O programa é compilado corretamente.

Diferentes convenções de nomenclatura para macros de guarda podem ser usadas por programadores diferentes. Outras formas comuns de exemplo acima incluem AVO_INCLUDED, NOMEDOCRIADOR_AAAAMMDD_HHMMSS (com a data apropriada substituída), e nomes gerados a partir de um UUID. (No entanto, nomes que começam com um ou dois underscores, como _AVO_H e __AVO_H, são reservados para a implementação e não devem ser usados pelo usuário.[1][2])

Claro, é importante evitar a duplicação do mesmo nome de uma include guard em diferentes arquivos cabeçalho, pois incluir o 1º vai impedir que o 2º seja incluído, levando a perda de quaisquer declarações, definições inline, ou outros #includes no 2º cabeçalho.

Dificuldades[editar | editar código-fonte]

Para que #include guards funcionem corretamente, cada guarda tem que testar e definir macros de pré-processador diferentes, condicionalmente. Portanto, um projeto usando #include guards deve criar um esquema coerente de atribuição de nomes para suas include guards, e certificar-se de que seu esquema não entra em conflito com quaisquer cabeçalhos usados de terceiros, ou com os nomes de quaisquer macros globalmente visíveis.

Por esta razão, a maioria das implementações de C e C++ fornecem uma diretiva não-padrão #pragma once. Esta diretiva, inserida na parte superior de um arquivo cabeçalho, irá garantir que o arquivo é incluído apenas uma vez. A linguagem Objective-C (que é um superconjunto de C) introduziu uma diretiva #import que funciona exatamente como #include, exceto que inclui cada arquivo apenas uma vez, eliminando assim a necessidade de #include guards.

Veja também[editar | editar código-fonte]

Referências[editar | editar código-fonte]

  1. C++ padrão (ISO/IEC 14882) seção 17.4.3.1.2/1
  2. C padrão (ISO/IEC 9899) seção 7.1.3/1.