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] та, особливо, жорсткі посилання[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]

Примітки[ред. | ред. код]

  1. Noel Llopis (25.01.2005). Games from Within: Even More Experiments with Includes. Games from Within. Архів оригіналу за 30.09.2008. Процитовано 19.08.2013. 
  2. The C Preprocessor: 1. The C Preprocessor. Gcc.gnu.org. 1996-02-01. Процитовано 2013-08-19. 
  3. "Clang" CFE Internals Manual — Clang 3.4 documentation. Clang.llvm.org. Процитовано 2013-08-19. 
  4. clang: File manipulation routines. Clang.llvm.org. Процитовано 2013-08-19. 
  5. а б GCC 3.4 Release Series — Changes, New Features, and Fixes. Gcc.gnu.org. Процитовано 2013-08-19. 
  6. should_stack_file() function in GCC source code. 
  7. clang: clang: Pragma.cpp Source File. Clang.llvm.org. Архів оригіналу за 2014-04-04. Процитовано 2013-08-19. 
  8. Comeau C++ Pre-Release User Documentation: Pragmas. Comeaucomputing.com. Архів оригіналу за 2013-12-11. Процитовано 2013-08-19. 
  9. #pragma once - RAD Studio XE3. Docwiki.embarcadero.com. 2010-12-02. Процитовано 2013-08-19. 
  10. Pragmas. Digital Mars. Процитовано 2013-08-19. 
  11. Alternatives to Wrapper #ifndef. Gcc.gnu.org. Процитовано 2013-08-20. 
  12. HP aC++/HP ANSI C A.06.26 ReleaseNotes. 
  13. Supported GCC pragmas. IBM. Процитовано 2015-02-20. 
  14. Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead.. Intel Developer Zones. Процитовано 4 December 2013. 
  15. once (C/C++). Msdn.microsoft.com. Процитовано 2013-08-19. 
  16. IDE help/documentation
  17. ARM Information Center. ARM. Процитовано 2013-12-17. 
  18. IAR C/C++ Development Guide. IAR Systems. Архів оригіналу за 16 травень 2017. Процитовано 4 December 2013. 
  19. Solaris Studio 12.4: C++ User's Guide. Oracle. Процитовано 2015-02-20. 
  20. Solaris Studio 12.4: C User's Guide. Oracle. Процитовано 2015-02-20.