Include guard

Материал из Seo Wiki - Поисковая Оптимизация и Программирование

Перейти к: навигация, поиск
Правильный заголовок этой статьи — #include guard. Он показан некорректно из-за технических ограничений.

В языках программирования Си и C++ директивы #include guards (защита подключения) иногда называется macro guard (макрозащита) — это особая конструкция, применяемая для избежания проблем с «двойным подключением» при использовании директивы компилятора #include. Добавление #include guards в заголовочный файл является, в общем-то, единственой возможностью сделать этот файл идемпотентным.

Содержание

Двойное подключение

Следующий фрагмент кода на языке Си демонстрируем потенциальные проблемы, которые могут возникнуть, если пропустить #include guards:

File «grandfather.h»
struct foo {
    int member;
};
File «father.h»
#include "grandfather.h"
File «child.c»
#include "grandfather.h"
#include "father.h"

Здесь к файлу «child.c» напрямую подключаются две копии заголовочного файла «grandfather.h». Это может вызвать ошибку компиляции, так как структура типа foo явным образом определяется дважды.

Применение #include guards

File «grandfather.h»
#ifndef H_GRANDFATHER
#define H_GRANDFATHER

struct foo {
    int member;
};

#endif
File «father.h»
#include "grandfather.h"
File «child.c»
#include "grandfather.h"
#include "father.h"

В даном примере, первое включение файла «grandfather.h» вызывает макроопределение H_GRANDFATHER. Далее, когда к «child.c» подключается «grandfather.h» второй раз, проверка #ifndef выдаёт ошибку, и препроцессор пропускает #endif, таким образом избегая второго определения struct foo. В результате программа компилируется корректно.

Проблемы использования

Чтобы #include guards работали корректно, каждую директиву необходимо проверить и, соответственно, каждая директива должна корректно пройти тест и набор условий различных инструкций препроцессора. Поэтому, проект с использованием #include guards должен отрабатывать связную схему наименования для подключаемых директив, и должен убеждаться, что схема не противоречит с используемыми посторонними заголовочными файлами или именами любых глобально видимых инструкций.

По этой причине, во многих случаях (в языках Си и C++) используется нестандартная директива #pragma once. Эта директива, указанная в начале заголовочного файла, будет указывать, что файл должен подключаться только один раз. Этот подход, однако, может плохо сказаться в виде потенциальной сложности определения ситуации, когда две директивы #include, указанные в разных местах, на самом деле ссылаются на один заголовок (например, при помощи символьной ссылки в Unix-подобных системах). Также, так как #pragma once не является стандартной директивой, её семантика может серьёзно изменяться в зависимости от применения.

Также смотри

Дополнительные источники

zh:Include防範 en:Include guard

Источник — «http://www.sbup.com/wiki/Include_guard»
Личные инструменты

Served in 0.090 secs.