Pragma once
У мовах програмування С та C++, #pragma once
— нестандартна, однак широкопідтримувана директива препроцесора, створена для того, аби забезпечити включення тіла файлу сирцевого коду (зазвичай заголовного файлу) лише один раз в одній одиниці трансляції. Таким чином, #pragma once
виконує ту ж функцію, що і #include guard[en], але з деякими перевагами, зокрема меншою кількістю коду, уникненням колізії імен та прискоренням швидкості компіляції (в окремих випадках).[1]
Приклад
- Файл «grandparent.h»
#pragma once struct foo { int member; };
- Файл «parent.h»
#include "grandparent.h"
- Файл «child.c»
#include "grandparent.h" // Буде оброблено визначення структури foo #include "parent.h" // Файл grandparent.h вже не включатиметься
Переваги
Найпоширенішою альтернативою #pragma once
є використання директиви #define
для створення include guard[en]-макроса, ім'я якого програміст вибирає унікальним для кожного файлу. Наприклад,
#ifndef GRANDPARENT_H #define GRANDPARENT_H // ... вміст grandparent.h #endif /* !GRANDPARENT_H */
Це складніший і, можливо, менш ефективний метод. Також він збільшує ризик внесення помилок, оскільки відсутні механізми для запобігання випадковому використанню одного й того ж імені макроса в декількох файлах, у результаті чого лише один з цих файлів буде включено. Цієї проблеми достатньо, щоб використання #pragma once
було корисним. Відповідальність за обробку #pragma once
лежить на компіляторі, тому програміст не може зробити помилку, яка спричинить конфлікт імен.
Використання #pragma once
замість include guards може, для деяких компіляторів, покращити швидкість компіляції, бо це механізм вищого рівня. Компілятор може порівняти імена файлів або їхні inode без необхідності сканування препроцесором C заголовочних файлів у пошуку директив #ifndef
та #endif
. Важливо відзначити, що такі компілятори, як GCC, Clang та компілятори на основі EDG[en] мають специфічні процедури для розпізнавання та оптимізації обробки include guards
, тому використання #pragma once
дає невелике прискорення або ж зовсім не сповільнює компіляцію.[2][3][4]
Недоліки
Ідентифікація того ж файлу на файловій системі може бути непростою задачею[5]. Символьні та, особливо, жорсткі посилання[en] можуть спричинити те, що один і той же файл існує під різними іменами у різних каталогах. Компілятор може використовувати евристичні методи, які порівнюють розмір, час модифікації та вміст файлів[6]. Це може призвести до протилежного ефекту коли файл скопійовано до різних частин проекту. При виконанні директиви #pragma once
ці файли можуть розглядатися як різні або як один і той же компіляторо-залежним чином.
Сумісність
Compiler | #pragma once |
---|---|
Clang | підтримується[7] |
Comeau C/C++[en] | підтримується[8] |
C++ Builder | підтримується[9] (з XE3) |
Digital Mars C++ | підтримується[10] |
GCC | підтримується[11] (з 3.4[5]) |
HP C/aC++[en] | підтримується[12] (принаймні з A.06.12) |
IBM XL C/C++[en] | підтримується[13] (з 13.1.1) |
Intel C++ Compiler | підтримується[14] |
Microsoft Visual C++ | підтримується[15] (з 4.2) |
Pelles C[it] | підтримується[16] |
ARM DS-5 | підтримується[17] |
IAR C/C++ | підтримується[18] |
Solaris Studio C/C++ | не підтримується[19][20] |
Примітки
- ↑ Noel Llopis (25.01.2005). Games from Within: Even More Experiments with Includes. Games from Within. Архів оригіналу за 30.09.2008. Процитовано 19.08.2013.
- ↑ The C Preprocessor: 1. The C Preprocessor. Gcc.gnu.org. 1 лютого 1996. Архів оригіналу за 25 квітня 2007. Процитовано 19 серпня 2013.
- ↑ "Clang" CFE Internals Manual — Clang 3.4 documentation. Clang.llvm.org. Архів оригіналу за 6 серпня 2013. Процитовано 19 серпня 2013.
- ↑ clang: File manipulation routines. Clang.llvm.org. Архів оригіналу за 11 листопада 2013. Процитовано 19 серпня 2013.
- ↑ а б GCC 3.4 Release Series — Changes, New Features, and Fixes. Gcc.gnu.org. Архів оригіналу за 10 липня 2010. Процитовано 19 серпня 2013.
- ↑ should_stack_file() function in GCC source code.
- ↑ clang: clang: Pragma.cpp Source File. Clang.llvm.org. Архів оригіналу за 4 квітня 2014. Процитовано 19 серпня 2013.
- ↑ Comeau C++ Pre-Release User Documentation: Pragmas. Comeaucomputing.com. Архів оригіналу за 11 грудня 2013. Процитовано 19 серпня 2013.
- ↑ #pragma once - RAD Studio XE3. Docwiki.embarcadero.com. 2 грудня 2010. Архів оригіналу за 12 грудня 2013. Процитовано 19 серпня 2013.
- ↑ Pragmas. Digital Mars. Архів оригіналу за 12 грудня 2013. Процитовано 19 серпня 2013.
- ↑ Alternatives to Wrapper #ifndef. Gcc.gnu.org. Архів оригіналу за 4 березня 2016. Процитовано 20 серпня 2013.
- ↑ HP aC++/HP ANSI C A.06.26 ReleaseNotes. Архів оригіналу за 23 червня 2016. Процитовано 14 травня 2016.
- ↑ Supported GCC pragmas. IBM. Архів оригіналу за 4 березня 2016. Процитовано 20 лютого 2015.
- ↑ Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead. Intel Developer Zones. Архів оригіналу за 11 грудня 2013. Процитовано 4 грудня 2013.
- ↑ once (C/C++). Msdn.microsoft.com. Архів оригіналу за 10 серпня 2016. Процитовано 19 серпня 2013.
- ↑ IDE help/documentation
- ↑ ARM Information Center. ARM. Архів оригіналу за 7 жовтня 2016. Процитовано 17 грудня 2013.
- ↑ IAR C/C++ Development Guide (PDF). IAR Systems. Архів оригіналу (PDF) за 16 травня 2017. Процитовано 4 грудня 2013.
- ↑ Solaris Studio 12.4: C++ User's Guide. Oracle. Архів оригіналу за 9 жовтня 2016. Процитовано 20 лютого 2015.
- ↑ Solaris Studio 12.4: C User's Guide. Oracle. Архів оригіналу за 4 березня 2016. Процитовано 20 лютого 2015.