Январь 27, 2021 / Комментарии 0 |
В языках программирования Си и C++ #include guards (защита подключения), иногда также называемая macro guard (макрозащита) — это особая конструкция, применяемая для избежания проблем с «двойным подключением» при использовании директивы компилятора #include. Добавление #include guards в заголовочный файл является одним из способов сделать этот файл идемпотентным, то есть таким, что многократные его подключения эквивалентны однократному и не приводят к ошибкам.
Следующий фрагмент кода на языке Си демонстрирует потенциальные проблемы, которые могут возникнуть, если пропустить #include guards:
Файл grandfather.h struct foo { int member; }; Файл father.h #include "grandfather.h" Файл child.c #include "grandfather.h" #include "father.h"
Здесь к файлу «child.c» напрямую подключаются две копии заголовочного файла «grandfather.h». Это может вызвать ошибку компиляции, так как структура типа foo явным образом определяется дважды.
Файл grandfather.h #ifndef H_GRANDFATHER #define H_GRANDFATHER struct foo { int member; }; #endif Файл father.h #include "grandfather.h" Файл 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 не является стандартной директивой, её семантика может серьёзно изменяться в зависимости от применения.
Читайте также
Гай Юлий Цезарь Страбон Вописк
Гай Юлий Цезарь Страбон Вописк (лат. Gaius Iulius Caesar Strabo
Третий сезон фэнтезийного драматического сериала «Гримм», премьера которого состоялась на
Эрнан Хорхе Креспо (исп. Hernan Jorge Crespo; род. 5 июля
Афганский Туркестан (перс. ترکستان افغان / Torkistâne Afghân; дари ترکستان
Доллар Зимбабве (англ. zimbabwean dollar) — денежная единица государства Зимбабве,
Валери Фихофф (нем. Valerie Viehoff; род. 16 февраля 1976, Бонн)
Вишневские (польск. Wiśniewski) — дворянские и графские роды. Существует целый
Марокко на летних Олимпийских играх 2016
Марокко на летних Олимпийских играх 2016 года будет представлена как
Чемпионат Европы по кёрлингу 2012
Чемпионат Европы по кёрлингу 2012 года состоялся в Карлстаде (Швеция)
Медицинская этика (медицинская деонтология) — дисциплина раздела прикладной этики, изучающая
Созвездия (англ. Constellations) — серия из 23 небольших гуашей Жоана
Брэдли Джонсон (англ. Bradley Johnson; 28 апреля 1987, Хакни) —
Эмиль Девенпорт Хирш (англ. Emile Davenport Hirsch; род. 13 марта
«Евстифейка-волк» — российский мультфильм Елены Ужиновой и Олега Ужинова, снят
Шура Кобер (5 ноября 1926, Николаев, Украинская ССР — 5