включить охранник - include guard

редактировать

В C и C ++ языков программирования, #include guard, иногда называемый macro guard, header guard или file guard, - это особая конструкция, используемая для избежать проблемы двойного включения при работе с директивой include.

Препроцессор C обрабатывает директивы формы #include в исходный файл путем нахождения связанного файлана диске и путем включения («включая») его содержимого в копию исходного файла известная как единица трансляции, заменяющая в процессе директиву include. Файлы, включенные в этом отношении, обычно представляют собой файлы заголовков , которые обычно содержат объявления из функций и классов или структур. Если определенные языковые конструкции C или C ++ определены дважды, результирующая единица перевода недействительна. Защитники #include предотвращают возникновение этой ошибочной конструкции из-за механизма двойного включения.

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

Содержание
  • 1 Двойное включение
    • 1.1 Пример
      • 1.1.1 Файл "grandparent.h"
      • 1.1.2 Файл "parent.h"
      • 1.1.3 Файл "child.c"
      • 1.1.4 Результат
  • 2 Использование #include guards
    • 2.1 Пример
      • 2.1.1 Файл "grandparent.h"
      • 2.1.2 Файл "parent.h"
      • 2.1.3 Файл "child.c"
      • 2.1.4 Результат
    • 2.2 Обсуждение
  • 3 Трудности
  • 4 См. Также
  • 5 Ссылки
  • 6 Внешние ссылки
Двойное включение

Пример

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

Файл "grandparent.h"

struct foo {int member; };

Файл "parent.h"

#include "grandparent.h"

Файл "child.c"

#include "grandparent.h" #include "parent.h"

Результат

struct foo {int member; }; struct foo {int member; };

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

Использование #include guards

Пример

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

Файл "grandparent.h"

#ifndef GRANDPARENT_H #define GRANDPARENT_H struct foo {int member; }; #endif / * GRANDPARENT_H * /

Файл "parent.h"

#include "grandparent.h"

Файл "child.c"

#include "grandparent.h" #include "родительский. h "

Результат

struct foo {int member; };

Здесь для первого включения "grandparent.h" определен макрос GRANDPARENT_H. Когда "child.c" включает "grandparent.h" во второй раз, поскольку тест #ifndefвозвращает false, препроцессор переходит к #endif, таким образом избегая второго определение struct foo. Программа компилируется правильно.

Обсуждение

Различные соглашения об именах для макроса защиты могут использоваться разными программистами. Другие распространенные формы приведенного выше примера включают GRANDPARENT_INCLUDED, CREATORSNAME_YYYYMMDD_HHMMSS(с заменой соответствующей информации о времени) и имена, сгенерированные из UUID. (Однако имена, начинающиеся с одного подчеркивания и заглавной буквы, или любое имя, содержащее двойное подчеркивание, например _GRANDPARENT__Hи __GRANDPARENT_H, являются зарезервировано для языковой реализации и не должно использоваться пользователем.)

Конечно, важно избегать дублирования одного и того же имени макроса include-guard в разных файлах заголовков, поскольку включение 1-го предотвратит 2-е от включения, что приведет к потере любых объявлений, встроенных определений или других #includes во втором заголовке.

Трудности

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

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

См. также
Ссылки
  1. ^C ++ стандарт (ISO / IEC 14882) раздел 17.4.3.1.2 / 1
  2. ^стандарт C (ISO / IEC 9899) раздел 7.1.3 / 1.
  3. ^«Цель C: определение классов». developer.apple.com. 2014-09-17. Проверено 3 октября 2018 г.
Внешние ссылки
Последняя правка сделана 2021-05-23 13:04:52
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте