Jump to content

прагма один раз

В C и C++ языках программирования #pragma once — это нестандартная, но широко поддерживаемая директива препроцессора , предназначенная для включения текущего файла заголовка только один раз в одну компиляцию. [1] Таким образом, #pragma once служит той же цели, что и include Guards , но имеет ряд преимуществ, включая меньшее количество кода, избежание конфликтов имен и иногда улучшение скорости компиляции. [2] Пока #pragma once доступен в большинстве современных компиляторов, его реализация сложна и не всегда надежна.

Файл "grandparent.h"
#pragma once

struct foo 
{
    int member;
};
Файл «parent.h»
#include "grandparent.h"
Файл "child.c"
#include "grandparent.h"
#include "parent.h"

В этом примере включение grandparent.h в обоих parent.h и child.c обычно вызывает ошибку компиляции, поскольку структура с заданным именем может быть определена только один раз в данной компиляции. #pragma once Директива служит для того, чтобы избежать этого, игнорируя последующие включения grandparent.h.

Преимущества

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

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

Самая распространенная альтернатива #pragma once это использовать #define чтобы установить макрос защиты #include , имя которого выбирается программистом как уникальное для этого файла. Например,

#ifndef GRANDPARENT_H
#define GRANDPARENT_H
... contents of grandparent.h
#endif /* !GRANDPARENT_H */

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

При отсутствии #include охранников вокруг #include директивы, использование #pragma once улучшит скорость компиляции для некоторых компиляторов, поскольку это механизм более высокого уровня; сам компилятор может сравнивать имена файлов или индексные дескрипторы без необходимости вызывать препроцессор C для сканирования заголовка на наличие #ifndef и #endif. Тем не менее, поскольку защита включения появляется очень часто, а накладные расходы на открытие файлов значительны, компиляторы обычно оптимизируют обработку защиты включения, делая их максимально быстрыми. #pragma once. [3] [4] [5]

Предостережения

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

Идентификация одного и того же файла в файловой системе — нетривиальная задача. [6] Символические ссылки и особенно жесткие ссылки могут привести к тому, что один и тот же файл будет найден под разными именами в разных каталогах. Компиляторы могут использовать эвристику, которая сравнивает размер файла, время модификации и содержимое. [7] Кроме того, #pragma once может поступить неправильно, если один и тот же файл намеренно скопирован в несколько частей проекта, например, при подготовке сборки. Хотя включение охранников все равно защитит от двойных определений, #pragma once может или не может рассматривать их как один и тот же файл в зависимости от компилятора. Эти трудности, а также трудности, связанные с определением того, что представляет собой один и тот же файл при наличии жестких ссылок, сетевых файловых систем и т. д., до сих пор препятствовали стандартизации #pragma once. [ нужна ссылка ]

Использование защитных макросов #include позволяет зависимому коду распознавать небольшие различия в семантике или интерфейсах конкурирующих альтернатив и реагировать на них. Например,

#include TLS_API_MACRO /* defined on the command line */

...

#if defined TLS_A_H
... use one known API
#elif defined TLS_B_H
... use another known API
#else
#error "unrecognized TLS API"
#endif

В этом случае для прямого определения доступности API будет использоваться тот факт, что включаемый файл объявил себя с помощью своего защитного макроса #include.

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

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

Портативность

[ редактировать ]
Компилятор Поддерживать
Кланг Да [8]
Комо C/C++ Да [9]
Крей C и C++ Да [10] (начиная с версии 9.0)
C++Builder Да [11] (только начиная с классического компилятора XE3.)
Цифровой Марс C++ Да [12]
Коллекция компиляторов GNU (GCC) Да [13] (официально с версии 3.4 [6] [14] )
HP C/aC++ Да [15] (по крайней мере, с A.06.12)
IBM XL C/С++ Да [16] (начиная с версии 13.1.1)
Intel C++-компилятор Да [17]
Microsoft Visual С++ Да [18] [19] (начиная с версии 4.2)
Компилятор NVIDIA CUDA Да (в зависимости от базового компилятора хоста)
Экскаваторы С Да [20]
АРМ ДС-5 Да [21]
И Си/С++ Да [22]
Инструменты для микроконтроллера Arm Keil: компиляторы C/C++ Да [23] (Я КЕЙЛ АРМСС 5)
OpenWatcom Да [24]
Oracle Developer Studio C/C++ Да [25] (с версии 12.5)
Портлендская группа C/C++ Да [26] (начиная с версии 17.4)
TinyCC Да [27] (с апреля 2015 г.)
СДКК Нет [28] (по состоянию на апрель 2024 г.)
ЗАДАЧИ Набор инструментов VX для TriCore: компилятор C Да [29] (начиная с версии 6.2r2)
Инструменты генерации кода Texas Instruments: компилятор C Да [30] (например, MSP430, ARM, C2000)
  1. ^ "один раз" . Документы Майкрософт . 3 ноября 2016 г. Проверено 25 июля 2019 г.
  2. ^ «Игры изнутри: еще больше экспериментов с включениями» . 25 января 2005 г. Архивировано из оригинала 30 сентября 2008 года . Проверено 19 августа 2013 г.
  3. ^ «Препроцессор C: 1. Препроцессор C» . Gcc.gnu.org. 1 февраля 1996 г. Проверено 19 августа 2013 г.
  4. ^ « Руководство по внутреннему устройству CFE «Clang» — документация Clang 3.4» . Clang.llvm.org . Проверено 19 августа 2013 г.
  5. ^ «clang: процедуры манипуляции файлами» . Clang.llvm.org . Проверено 19 августа 2013 г.
  6. ^ Перейти обратно: а б «Серия выпусков GCC 3.4 — изменения, новые функции и исправления» . Gcc.gnu.org . Проверено 19 августа 2013 г.
  7. ^ «функция must_stack_file() в исходном коде GCC» .
  8. ^ «clang: clang: Исходный файл Pragma.cpp» . Clang.llvm.org. Архивировано из оригинала 4 апреля 2014 г. Проверено 19 августа 2013 г.
  9. ^ «Предварительная пользовательская документация Comeau C++: Pragmas» . Comeaucomputing.com. Архивировано из оригинала 11 декабря 2013 г. Проверено 19 августа 2013 г.
  10. ^ «Обзор выпуска CCE 9.0.0. Введение S-5212» . Cray Inc. 01.06.2019 . Проверено 23 сентября 2019 г.
  11. ^ «#pragma Once — RAD Studio XE3» . Docwiki.embarcadero.com. 02.12.2010 . Проверено 19 августа 2013 г.
  12. ^ «Прагмы» . Цифровой Марс . Проверено 19 августа 2013 г.
  13. ^ «Альтернативы обертке #ifndef» . Gcc.gnu.org . Проверено 20 августа 2013 г.
  14. ^ «Ошибка GCC 11569 — нет замены #pragma Once» . 18 июля 2003 г. Проверено 21 октября 2020 г.
  15. ^ «Руководство программиста HP aC++/HP C A.06.29; март 2016 г. (AR1603)» .
  16. ^ «Прагмы GCC» . ИБМ . Проверено 20 февраля 2015 г.
  17. ^ «Диагностика 1782: #pragma Once устарела. Вместо этого используйте #ifndef Guard» . Зоны разработчиков Intel . Архивировано из оригинала 31 января 2012 года . Проверено 4 декабря 2013 г. #pragma Once должна продолжать работать (в настоящее время НЕ устарела) с компилятором Intel.
  18. ^ «один раз (C/C++)» . Сеть разработчиков Microsoft. Архивировано из оригинала 10 августа 2016 г. Проверено 19 августа 2013 г.
  19. ^ «однажды прагма | Microsoft Docs» .
  20. ^ Справка/документация IDE
  21. ^ «Информационный центр АРМ» . РУКА . Проверено 17 декабря 2013 г.
  22. ^ «Руководство по разработке IAR C/C++» (PDF) . ИАР СИСТЕМЫ . Проверено 1 марта 2023 г.
  23. ^ «Прагмы, распознаваемые компилятором» . Кейл.
  24. ^ «#pragma Once не работает, если файлы, на которые ссылаются альтернативные пути» . Теперь это должно быть исправлено в репозитории git.
  25. ^ «Oracle® Developer Studio 12.5: Руководство по совместимости с GCC» . Оракул . Проверено 26 июля 2016 г.
  26. ^ «Портлендская группа» . Проверено 31 июля 2016 г.
  27. ^ «Прагма TinyCC после реализации» . Проверено 19 июня 2018 г.
  28. ^ «Руководство пользователя компилятора SDCC, раздел 3.16, стр. 62» (PDF) . Проверено 11 апреля 2024 г.
  29. ^ «МА160-800 (v6.2r2) 13 марта 2018 г., стр. 92» (PDF) .
  30. ^ «[EXT_EP-8185] Документ #pragma Once» . Встроенное программное обеспечение и инструменты . Отчет о проблемах с программным обеспечением — Texas Instruments. Архивировано из оригинала 29 января 2022 года.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 69395852e41276706b517cd0fdd6c776__1719922440
URL1:https://arc.ask3.ru/arc/aa/69/76/69395852e41276706b517cd0fdd6c776.html
Заголовок, (Title) документа по адресу, URL1:
pragma once - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)