Pragma once c что это
Здравствуйте, gde11, Вы писали:
G>subj — читал в MSDN, но так и не понял. Для чего она нужна?
Хотелось бы дополнить вопрос.
Насколько я понял #pragma используется для дополнительных указаний компилятору (естественно параметры зависят от компилятора), поэтому корректнее было бы если бы уважаемый gde11 указал для какого компилятора необходимо объяснение.
Или я совсем не прав?
Re: Что такое #pragma once ?
| От: | addword |
| Дата: | 18.11.03 15:49 |
| Оценка: |
Здравствуйте, gde11, Вы писали:
G>subj — читал в MSDN, но так и не понял. Для чего она нужна?
Это чтобы файл включался дерективой #include не больше одного раза. Раньше этого эффекта добивались при помощи определения макросов и проверки их определения.
Типа
#ifndef THIS_FILE_INCLUDED
#define THIS_FILE_INCLUDED
Re: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 18.11.03 15:50 |
| Оценка: |
Здравствуйте, gde11, Вы писали:
G>subj — читал в MSDN, но так и не понял. Для чего она нужна?
что бы не писать в каждом .h файле
#ifndef ___myfile_included
#define ___myfile_included
// собственно файл
#endif
тк редки случаи, когда надо один .h файл посуществу подключать более одного раза.
—
С уважением,
Сергей Мухин
Re: Что такое #pragma once ?
| От: | Андрей Галюзин |
| Дата: | 18.11.03 16:07 |
| Оценка: |
g> subj — читал в MSDN, но так и не понял. Для чего она нужна?
Хочу добавить, что #pragma once — это не замена для include guards, а дополнение, которое позволяет компилятору не открывать
файл заголовка и поэтому ускоряет компиляцию.
А в случаях со связями (links) в ntfs, ext2 и пр. #pragma once не работает.
#ifndef H_FILE_INCLUDED #define H_FILE_INCLUDED #if defined _MSC_VER && _MSC_VER >= 1000 #pragma once #endif // содержимое заголовка #endif // H_FILE_INCLUDED
Posted via RSDN NNTP Server 1.7 «Bedlam»
Re[2]: Что такое #pragma once ?
| От: | gde11 |
| Дата: | 18.11.03 16:48 |
| Оценка: |
Здравствуйте, Ash-2, Вы писали:
A2>Хотелось бы дополнить вопрос.
A2>Насколько я понял #pragma используется для дополнительных указаний компилятору (естественно параметры зависят от компилятора), поэтому корректнее было бы если бы уважаемый gde11 указал для какого компилятора необходимо объяснение.
Для Visual C++ 6.0
Re[2]: Что такое #pragma once ?
| От: | gde11 |
| Дата: | 18.11.03 16:53 |
| Оценка: |
Здравствуйте, SergeMukhin, Вы писали:
SM>что бы не писать в каждом .h файле
SM>#ifndef ___myfile_included
SM>#define ___myfile_included
SM>// собственно файл
SM>#endif
SM>тк редки случаи, когда надо один .h файл посуществу подключать более одного раза.
Хм, я вот так и понял. Вот только тогда для чего в Visual C+ 6.0 в коде MFC AppWizard включено и то и другое? Непонятно
Re[2]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 09:17 |
| Оценка: |
Здравствуйте, Ash-2, Вы писали:
A2>Здравствуйте, gde11, Вы писали:
G>>subj — читал в MSDN, но так и не понял. Для чего она нужна?
A2>Хотелось бы дополнить вопрос.
A2>Насколько я понял #pragma используется для дополнительных указаний компилятору (естественно параметры зависят от компилятора), поэтому корректнее было бы если бы уважаемый gde11 указал для какого компилятора необходимо объяснение.
A2>Или я совсем не прав?
имеется ввиду MS, версии так с 6-й, а может и раньше
—
С уважением,
Сергей Мухин
Re[3]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 09:37 |
| Оценка: |
Здравствуйте, gde11, Вы писали:
G>Здравствуйте, SergeMukhin, Вы писали:
SM>>что бы не писать в каждом .h файле
SM>>#ifndef ___myfile_included
SM>>#define ___myfile_included
SM>>// собственно файл
SM>>#endif
SM>>тк редки случаи, когда надо один .h файл посуществу подключать более одного раза.
G>Хм, я вот так и понял. Вот только тогда для чего в Visual C+ 6.0 в коде MFC AppWizard включено и то и другое? Непонятно
тк #pragma once поддерживают не все компиляторы, то лучше писать
#ifde _MSC && _VER > 1200
#pragma once
#endif
при этом, естесственно надо оставлять обычный #ifndef
но как это все лень! и поэтому я давно уже ставлю только #pragma once
#pragma once существенно ускоряет работу компилятора, т.к. даже если условие в #ifndef срабатывает, то компилятор все равно прогоняет этот файл через себя (правда не все шаги).
—
С уважением,
Сергей Мухин
Re[4]: Что такое #pragma once ?
| От: | Tuo_Bellas |
| Дата: | 19.11.03 10:02 |
| Оценка: |
Здравствуйте, SergeMukhin, Вы писали:
SM>тк #pragma once поддерживают не все компиляторы, то лучше писать
SM>#ifde _MSC && _VER > 1200
SM>#pragma once
SM>#endif
SM>при этом, естесственно надо оставлять обычный #ifndef
SM>но как это все лень! и поэтому я давно уже ставлю только #pragma once
На сколько я понимаю, компилятор обязан игнорировать неизвестные ему прагмы. А вероятность того, что твой код будут компилировать на какой-то экзотике где #pragma once есть и означает что-то другое обычно весьма мала. (Если нет — очевидно нужно использовать #if defined _MSC_VER. )
Re[5]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 10:28 |
| Оценка: |
Здравствуйте, Tuo_Bellas, Вы писали:
T_B>Здравствуйте, SergeMukhin, Вы писали:
SM>>тк #pragma once поддерживают не все компиляторы, то лучше писать
SM>>#ifde _MSC && _VER > 1200
SM>>#pragma once
SM>>#endif
SM>>при этом, естесственно надо оставлять обычный #ifndef
SM>>но как это все лень! и поэтому я давно уже ставлю только #pragma once
T_B>На сколько я понимаю, компилятор обязан игнорировать неизвестные ему прагмы. А вероятность того, что твой код будут компилировать на какой-то экзотике где #pragma once есть и означает что-то другое обычно весьма мала. (Если нет — очевидно нужно использовать #if defined _MSC_VER. )
T_B>Tuo_Bellas.
игнорирование игнорированию рознь. MS выдает warning
e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
а у меня установлено warning as error
да и вообще не красиво warning получать.
—
С уважением,
Сергей Мухин
Re[6]: Что такое #pragma once ?
| От: | Shroo |
| Дата: | 19.11.03 11:50 |
| Оценка: |
Здравствуйте, SergeMukhin, Вы писали:
SM>игнорирование игнорированию рознь. MS выдает warning
SM>e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
SM>а у меня установлено warning as error
SM>да и вообще не красиво warning получать.
Ну на счет warning as error — это ты погорячился.
Re[7]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 13:11 |
| Оценка: |
Здравствуйте, Shroo, Вы писали:
S>Здравствуйте, SergeMukhin, Вы писали:
SM>>игнорирование игнорированию рознь. MS выдает warning
SM>>e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
SM>>а у меня установлено warning as error
SM>>да и вообще не красиво warning получать.
S> Ну на счет warning as error — это ты погорячился.
нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
—
С уважением,
Сергей Мухин
Re[8]: Что такое #pragma once ?
| От: | Shroo | |
| Дата: | 19.11.03 13:27 | |
| Оценка: | +1 | |
Здравствуйте, SergeMukhin, Вы писали:
SM>Здравствуйте, Shroo, Вы писали:
S>>Здравствуйте, SergeMukhin, Вы писали:
SM>>>игнорирование игнорированию рознь. MS выдает warning
SM>>>e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
SM>>>а у меня установлено warning as error
SM>>>да и вообще не красиво warning получать.
S>> Ну на счет warning as error — это ты погорячился.
SM>нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
Да дело же не в том. Просто такой подход раздражает во время работы. Например, тебе надо что-то быстро скомпилить несколько раз и тебе плевать на то, что у тебя (вроде как) потеря данных при преобразовании типов, а тебе в ответ: ERROR. А когда компилятор не дает тебе работать из-за того, что считает, что у тебя ошибка — это. хм.. в общем, не нравится мне это. Лично я считаю, что все варнинги надо исправлять (какие-то отключать ), но программист должен иметь возможност делать тогда, когда считает нужным!
Re[8]: Что такое #pragma once ?
| От: | Shroo |
| Дата: | 19.11.03 13:30 |
| Оценка: |
Здравствуйте, SergeMukhin, Вы писали:
SM>Здравствуйте, Shroo, Вы писали:
S>>Здравствуйте, SergeMukhin, Вы писали:
SM>>>игнорирование игнорированию рознь. MS выдает warning
SM>>>e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
SM>>>а у меня установлено warning as error
SM>>>да и вообще не красиво warning получать.
S>> Ну на счет warning as error — это ты погорячился.
SM>нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
Кстати, могу поспорить, что подавляющее большинство людей тут не используют warrning as errors . ну, просто мне так кажется.
Re[8]: Что такое #pragma once ?
| От: | _Jane_ |
| Дата: | 19.11.03 14:47 |
| Оценка: |
Здравствуйте, SergeMukhin, Вы писали:
SM>нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
Если пользоваться некоторыми реализациями stl то все приплыли — там _такая_гора_ ворнингов типа «unreferenced parameter. »
И еще иногда «достают» сгенерированные корбой исходники, но тут в принципе легче т.к. отключить именно их можно временно, только на время обработки #include файла, а stl-ские так не получится.
Вроде и код чужой, подправить нельзя. И уж тем более warning as error ставить т.к. не скомпилится И отключать ворнинги вообще — нехорошо. Так и живем.

Jane
Re[9]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 15:01 |
| Оценка: |
Здравствуйте, Shroo, Вы писали:
S>Здравствуйте, SergeMukhin, Вы писали:
SM>>Здравствуйте, Shroo, Вы писали:
S>>>Здравствуйте, SergeMukhin, Вы писали:
SM>>>>игнорирование игнорированию рознь. MS выдает warning
SM>>>>e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
SM>>>>а у меня установлено warning as error
SM>>>>да и вообще не красиво warning получать.
S>>> Ну на счет warning as error — это ты погорячился.
SM>>нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
S> Да дело же не в том. Просто такой подход раздражает во время работы. Например, тебе надо что-то быстро скомпилить несколько раз и тебе плевать на то, что у тебя (вроде как) потеря данных при преобразовании типов, а тебе в ответ: ERROR. А когда компилятор не дает тебе работать из-за того, что считает, что у тебя ошибка — это. хм.. в общем, не нравится мне это. Лично я считаю, что все варнинги надо исправлять (какие-то отключать ), но программист должен иметь возможност делать тогда, когда считает нужным!
если тебе надо быстро «скомпилить» (я бы сказал скомпилировать), то конечно warning as error вреден, но часто это нужно? только для маленьких программ, извини, у меня их нет. В промышленных проектах warning as error в самый раз. К сожалению MS не позволяет поставить уровень варнингов 4
—
С уважением,
Сергей Мухин
Re[9]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 15:11 |
| Оценка: |
Здравствуйте, Shroo, Вы писали:
S>Здравствуйте, SergeMukhin, Вы писали:
SM>>Здравствуйте, Shroo, Вы писали:
S>>>Здравствуйте, SergeMukhin, Вы писали:
SM>>>>игнорирование игнорированию рознь. MS выдает warning
SM>>>>e:\VP70\_sources\Compiler\CPart\Tools\Source\GenObj.cpp(2) : warning C4068: unknown pragma
SM>>>>а у меня установлено warning as error
SM>>>>да и вообще не красиво warning получать.
S>>> Ну на счет warning as error — это ты погорячился.
SM>>нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
S> Кстати, могу поспорить, что подавляющее большинство людей тут не используют warrning as errors . ну, просто мне так кажется.
ты у нас большевик може быть?
при чем тут большинство? это не аргумент
—
С уважением,
Сергей Мухин
Re[9]: Что такое #pragma once ?
| От: | SergeMukhin |
| Дата: | 19.11.03 15:11 |
| Оценка: |
Здравствуйте, _Jane_, Вы писали:
_J_>Здравствуйте, SergeMukhin, Вы писали:
SM>>нет. больлшинство варнингов все таки о чем-то предупреждают не хорошем. лучше тексты держать красивыми, без них. если конечно ты пишешь только для себя, то на это можно наплевать
_J_>Если пользоваться некоторыми реализациями stl то все приплыли — там _такая_гора_ ворнингов типа «unreferenced parameter. »
_J_>И еще иногда «достают» сгенерированные корбой исходники, но тут в принципе легче т.к. отключить именно их можно временно, только на время обработки #include файла, а stl-ские так не получится.
_J_>Вроде и код чужой, подправить нельзя. И уж тем более warning as error ставить т.к. не скомпилится И отключать ворнинги вообще — нехорошо. Так и живем.
если есть много варнингов, то надо их отключать (совсем, в проекте, в данном месте) т.к. когда появится новый варнинг, на который тебе надо отреагировать ты его не увидишь за лесом старых.
—
С уважением,
Сергей Мухин
Re[10]: Что такое #pragma once ?
| От: | _Jane_ |
| Дата: | 19.11.03 15:27 |
| Оценка: |
Здравствуйте, SergeMukhin, Вы писали:
SM>если есть много варнингов, то надо их отключать (совсем, в проекте, в данном месте) т.к. когда появится новый варнинг, на который тебе надо отреагировать ты его не увидишь за лесом старых.
Что могу отключаю примерно таким способом
#pragma warning (disable:)
#include «alien_header_produces_warning.h»
#pragma warning (default:)
К сожалению это не совсем работает с шаблонами.
В проекте или совсем отключать не решаюсь — так можно пропустить какие-то проблемы и нажить себе неудовольствие руководства. В принципе, уже набила руку писать код так чтобы простых ворнингов в своих файлах не было теперь довольствуюсь тем что иногда просматриваю build окошко, так на всякий случай.

Jane
Pragma once
Правильный заголовок этой статьи — #pragma once . Он показан некорректно из-за технических ограничений.
В языках программирования Си и C++ #pragma once — нестандартная, но широко распространенная препроцессорная директива, разработанная для контроля за тем, чтобы конкретный исходный файл при компиляции подключался строго один раз. То есть, #pragma once применяется для тех же целей, что и include guard, но требует меньше кода и не допускает возможности коллизии имен.
В статье об include guard приводится пример ситуации, в которой нужно использовать тот или иной метод. Выходом является использование include guard, приведенное там же; Вариантом использования #pragma once может быть:
#pragma once struct foo int member; >;
File «father.h»
#include "grandfather.h"
File «child.c»
#include "grandfather.h" #include "father.h"
Достоинства и недостатки
Применение #pragma once вместо include guard увеличит скорость компиляции во многих случаях благодаря высокоуровневому механизму; компилятор может самостоятельно сравнивать имена файлов или inode’ы без необходимости вызова препроцессора Си для проверки заголовка на наличие #ifndef и #endif .
С другой стороны, некоторые компиляторы, как например, GCC, также использует специальный код для распознавания и оптимизации обработки include guard. [1]
Из-за того, что компилятор сам по себе отвечает за обработку #pragma once , программисту нет необходимости создавать новые имена, как например, GRANDFATHER_H в примере статьи об Include guard. Это исключает риск коллизии имён, то есть заголовочный файл не сможет вызвать ошибку при его подключении. Также приходится меньше набирать текст, нежели при использовании include guard.
Тем не менее, такая высокоуровневая обработка ускоряется в обоих случаях, но программисту приходится полагаться на корректную обработку компилятором #pragma once . Если компилятор совершает ошибку, например, не может распознать ситуацию, когда две символьные ссылки с различными именами указывают на один и тот же файл, то компиляция завершается с ошибкой. Компиляторы, содержащие ошибки, связанные с #pragma once , используются в LCC-Win32 версии 2004 года [2] [3] и GCC версии 1998 года. [1] GCC первоначально выдавал предупреждение об отключении #pragma once , если компилируемый код использовал её. Тем не менее, в релизе 3.4 GCC код обработки команды #pragma once был исправлен для корректной работы с символьными и жёсткими ссылками. Данная возможность была сочтена полезной и предупреждение было убрано. [4] [5]
Можно использовать обе команды, #pragma once и include guards, для написания переносимого кода, что также может принести выгоду от применения #pragma once при оптимизации (если компилятор её поддерживает):
#pragma once #ifndef GRANDFATHER_H #define GRANDFATHER_H struct foo int member; >; #endif /* GRANDFATHER_H */
Примечания
- ↑ 12The C Preprocessor. Once-Only Include Files
- ↑Сообщение из обсуждения standard change. Lcc-win32 accepts and implements #pragma once
- ↑Сообщение из обсуждения thoughts on an old proposal: #once
- ↑Obsolete once-only headers
- ↑GCC 3.4 Release Series. Changes, New Features, and Fixes
#ifndef/#define VS #pragma once [дубликат]
Фундаментальное отличие заключается в том, что #pragma once относится ко всему заголовочному файлу целиком. Изначальной идеей #pragma once было то, что в процессе обработки отдельной единицы трансляции компилятор (препроцессор) имеет право даже и не искать и не открывать второй раз заголовочные файлы, которые содержат #pragma once . Именно в этой форме когда-то и предлагалось стандартизовать #pragma once — как средство ускорения компиляции.
Include guards #ifdef/#endif , понятное дело, имеют право покрывать не весь заголовочный файл, т.е. эта пара в общем случае не относится ко всему файлу целиком. Это означает, что в общем случае компилятор будет вынужден найти и открыть заголовочный файл, чтобы включить участки, не попавшие внутрь #ifdef/#endif .
В то же время понятно, что компилятору не составляет никакого труда проанализировать содержимое заголовочного файла при первом прочтении и распознать явное идиоматическое использование #ifdef/#endif , прокрывающее весь файл целиком от начала до конца. В такой ситуации #pragma once не предоставляет никакой практической выгоды по сравнению с #ifdef/#endif . Именно по этой причине от стандартизации #pragma once в свое время отказались — как от фичи, не привносящей никакой дополнительной ценности (кроме, разве что, компактной записи и того, что, как заметили @vp_arth и @VladD, нет необходимости выдумывать уникальный идентификатор).
Соответственно, ответ очевиден — пользуйтесь стандартной функциональностью #ifdef/#endif и забудьте про нестандартный #pragma once . Может быть в каком-то случае вы заметите, что компилятор (препроцессор) не хочет оптимизировать обработку на основе анализа #ifdef/#endif и использование #pragma once действительно ускоряет компиляцию. Тогда, если для вас это критично — может быть стоит добавить в ваши файлы #pragma once .
Еще одно соображение против стандартизации #pragma once заключалось в том, что для обеспечения жесткой гарантии ее спецификации (т.е. строго единственного включения), необходимо иметь возможность надежно определять идентичность файла по указанному в директиве #include пути. Это задача в общем случае исключительно трудноразрешима во многих существующих файловых системах. Поэтому будьте осторожны с наивными пионерскими заявлениями типа «все современные компиляторы поддерживают #pragma once «. Ни о какой поддержке строгой спецификации ни в одном компиляторе речи не идет. И, разумеется, ни о каких гарантиях одинаковости поведения между компиляторами речи не идет тоже. По этой причине, если вы таки соберетесь использовать #pragma once в своем коде, используйте ее вместе с include guards, а не вместо их.
P.S. Включение других заголовочных файлов обычно «кладут» внутрь вашего #ifdef/#endif . Им нет никакой причины находиться снаружи. Манерой оставлять их снаружи вы, возможно, рискуете подавить вышеупомянутую оптимизацию. Если уж вы пользуетесь #ifdef/#endif , то в подавляющем большинстве случаев они должны покрывать весь файл от начала до конца.
#pragma once
Нередко (см. обсуждение на BoostDev, StackOverflow) поднимается вопрос о том, каким образом лучше оформлять .h файлы. Использовать ли стандартный метод «стражей включения», нестандартную, но поддерживаемую большинством компиляторов директиву #pragma once или же комбинацию и того и другого (и если комбинировать, то что ставить в начале файла). Я сам нередко колебался между этими вариантами в своём коде и сейчас решил изложить свою текущую точку зрения.
Преимущества #pragma once
- Ускорение компиляции, так как не надо повторно прогонять файл через препроцессор (тем не менее, современные компиляторы (например, GCC) нередко способны распознать наличие стражей включения, в таком случае #pragma once уже не даст ускорения).
- Чище код: одна короткая строчка вместо трёх, две из которых — длинные.
- Не надо выдумывать название макроса. Макрос может привести к конфликту имён. Например, при переносе содержимого в другой файл можно забыть поменять имя макроса, и, в случае дублирования, нужный файл не будет включён, а это трата нервов на поиски невнятных ошибок компиляции.
Недостатки #pragma once
- Нет поддержки стандартами C и C++, следовательно, компилятор не обязан понимать эту директиву. По стандарту неподдерживаемая pragma должна быть проигнорирована, и, скорее всего, компилятор не выдаст даже предупреждения, что, опять же, может привести к невнятным ошибкам компиляции вроде «переопределения символа». Ещё хуже, если компилятор будет вкладывать в #pragma once совсем иной смысл (такие примеры мне не известны, но всё же)…
Указанный недостаток можно частично побороть, скомбинировав стражи включения с #pragma once. При этом рекомендуется размещать #ifndef/#define в самом начале файла даже до комментариев, а #endif размещать последней строчкой (возможно существование компиляторов, которые проводят минимальный предварительный анализ файлов, поэтому такое размещение увеличивает вероятность ускорения компиляции сферическим компилятором в вакууме).
Нежелание комитета по стандартизации включить #pragma once в стандарт C++ вызывает сожаление. Не C, а именно C++, потому что в случае «чистого» си минимальный компилятор может быть действительно маленьким, что может быть важно на определённых платформах. В случае же стандартного C++ или, тем более, C++11, компилятор маленьким быть не может заведомо, он обречён быть своеобразным программным «монстром». Большинство компиляторов её и так уже поддерживают (мне не известны современные компиляторы C++, не поддерживающие #pragma once). Мотивация вида «у нас уже есть стандартный метод» никуда не годится, потому что этот «стандартный метод» очевидный overkill/костыль и не лишён недостатков (иногда даже бывает так).
Итак, на данный момент я использую #pragma once без стражей включения в C++ коде. Я использую стражи включения без #pragma once в переносимом plain C коде.