Include guard
Эта статья или раздел нуждается в переработке. Пожалуйста, улучшите статью в соответствии с правилами написания статей.
|
- Правильный заголовок этой статьи — #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
не является стандартной директивой, её семантика может серьёзно изменяться в зависимости от применения.
Также смотри
Дополнительные источники
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....