Include guard
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 struct
foo
. 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.