inclui guarda - include guard
Nas linguagens de programação C e C ++ , um #include guard , às vezes chamado de macro guard , header guard ou file guard , é uma construção particular usada para evitar o problema de dupla inclusão ao lidar com a diretiva include .
O pré- processador C processa as diretivas do formulário #include <file>em um arquivo de origem , localizando o associado fileno disco e transcluindo ("incluindo") seu conteúdo em uma cópia do arquivo de origem conhecido como unidade de tradução , substituindo a diretiva de inclusão no processo. Os arquivos incluídos a esse respeito são geralmente arquivos de cabeçalho , que normalmente contêm declarações de funções e classes ou estruturas . Se certas construções de linguagem C ou C ++ são definidas duas vezes , a unidade de tradução resultante é inválida . #include guardas evita que esta construção errônea surja pelo mecanismo de dupla inclusão.
A adição de #include guardas a um arquivo de cabeçalho é uma maneira de tornar esse arquivo idempotente . Outra construção para combater a inclusão dupla é #pragma uma vez , que não é padrão, mas é quase universalmente compatível entre os compiladores C e C ++ .
Inclusão dupla
Exemplo
O código C a seguir demonstra um problema real que pode surgir se #include guardas estiverem faltando:
Arquivo "grandparent.h"
struct foo {
int member;
};
Arquivo "parent.h"
#include "grandparent.h"
Arquivo "child.c"
#include "grandparent.h"
#include "parent.h"
Resultado
struct foo {
int member;
};
struct foo {
int member;
};
Aqui, o arquivo "child.c" inclui indiretamente duas cópias do texto no arquivo de cabeçalho "grandparent.h". Isso causa um erro de compilação , pois o tipo de estrutura fooserá definido duas vezes. Em C ++, isso seria chamado de violação da regra de definição única .
Uso de #include guardas
Exemplo
Nesta seção, o mesmo código é usado com a adição de #include guardas. O pré- processador C pré- processa os arquivos de cabeçalho, incluindo e posteriormente pré-processando-os recursivamente . Isso resultará em um arquivo fonte correto, como veremos.
Arquivo "grandparent.h"
#ifndef GRANDPARENT_H
#define GRANDPARENT_H
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
Arquivo "parent.h"
#include "grandparent.h"
Arquivo "child.c"
#include "grandparent.h"
#include "parent.h"
Resultado
struct foo {
int member;
};
Aqui, a primeira inclusão de "grandparent.h" tem a macro GRANDPARENT_Hdefinida. Quando "child.c" inclui "grandparent.h" na segunda vez, como o #ifndefteste retorna false, o pré-processador salta para o #endif, evitando assim a segunda definição de struct foo. O programa é compilado corretamente.
Discussão
Diferentes convenções de nomenclatura para a macro de guarda podem ser usadas por diferentes programadores . Outras formas comuns do exemplo acima incluem GRANDPARENT_INCLUDED, CREATORSNAME_YYYYMMDD_HHMMSS(com a informação de tempo apropriada substituída) e nomes gerados a partir de um UUID . (No entanto, nomes que começam com um sublinhado e uma letra maiúscula ou qualquer nome que contenha sublinhado duplo, como _GRANDPARENT__He __GRANDPARENT_H, são reservados para a implementação da linguagem e não devem ser usados pelo usuário.)
Obviamente, é importante evitar a duplicação do mesmo nome de macro de inclusão-guarda em arquivos de cabeçalho diferentes, pois incluir o primeiro impedirá que o segundo seja incluído, levando à perda de quaisquer declarações, definições inline ou outros #includes no 2º cabeçalho.
Dificuldades
Para que #include guardas funcionem corretamente, cada guarda deve testar e definir condicionalmente uma macro de pré-processador diferente. Portanto, um projeto que usa #include guardas deve elaborar um esquema de nomenclatura coerente para seus guardas de inclusão e certificar-se de que seu esquema não entre em conflito com o de quaisquer cabeçalhos de terceiros que usa, ou com os nomes de quaisquer macros visíveis globalmente.
Por esse motivo, a maioria das implementações C e C ++ fornecem uma #pragma oncediretiva fora do padrão . Esta diretiva, inserida no topo de um arquivo de cabeçalho, irá garantir que o arquivo seja incluído apenas uma vez. A linguagem Objective-C (que é um superconjunto de C) introduziu uma #importdiretiva, que funciona exatamente como #include, exceto que inclui cada arquivo apenas uma vez, evitando assim a necessidade de #include guardas.
Veja também
Referências
- ^ Padrão C ++ (ISO / IEC 14882) seção 17.4.3.1.2 / 1
- Padrão ^ C (ISO / IEC 9899) seção 7.1.3 / 1.
- ^ "Objetivo C: Definindo Classes" . developer.apple.com . 17/09/2014 . Página visitada em 03/10/2018 .