Jump to content

Pragma once: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
{{correct title}}
m Clean up spacing around commas and other punctuation fixes, replaced: , → ,
 
(23 intermediate revisions by 17 users not shown)
Line 1: Line 1:
{{short description|Preprocessor directive in C and C++}}
{{short description|Preprocessor directive in C and C++}}
{{correct title|title=#pragma once|reason=#}}
{{lowercase title}}
{{correct title|title=#pragma once|reason=#}}


In the [[C (programming language)|C]] and [[C++]] programming languages, <code>'''#pragma once'''</code> is a non-standard but widely supported [[C preprocessor|preprocessor directive]] designed to cause the current [[source file]] to be included only once in a single compilation.<ref>{{cite web |title=once |url=https://docs.microsoft.com/en-us/cpp/preprocessor/once |website=Microsoft Docs |accessdate=25 July 2019 |date=3 November 2016}}</ref> Thus, <code>#pragma once</code> serves the same purpose as [[include guard]]s, but with several advantages, including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.<ref>{{cite web|url=http://www.gamesfromwithin.com/articles/0501/000067.html |title=Games from Within: Even More Experiments with Includes |date=2005-01-25 |accessdate=2013-08-19 |url-status=dead |archiveurl=https://web.archive.org/web/20080930061318/http://www.gamesfromwithin.com/articles/0501/000067.html |archivedate=September 30, 2008 }}</ref> On the other hand, <code>#pragma once</code> is not necessarily available in all compilers and its implementation is tricky and might not always be reliable.
In the [[C (programming language)|C]] and [[C++]] programming languages, <code>'''#pragma once'''</code> is a non-standard but widely supported [[C preprocessor|preprocessor directive]] designed to cause the current header file to be included only once in a single compilation.<ref>{{cite web |title=once |url=https://docs.microsoft.com/en-us/cpp/preprocessor/once |website=Microsoft Docs |accessdate=25 July 2019 |date=3 November 2016}}</ref> Thus, <code>#pragma once</code> serves the same purpose as [[include guard|#include guards]], but with several advantages, including less code, avoidance of name clashes, and sometimes improvement in compilation speed.<ref>{{cite web|url=http://www.gamesfromwithin.com/articles/0501/000067.html |title=Games from Within: Even More Experiments with Includes |date=2005-01-25 |accessdate=2013-08-19 |url-status=dead |archiveurl=https://web.archive.org/web/20080930061318/http://www.gamesfromwithin.com/articles/0501/000067.html |archivedate=September 30, 2008 }}</ref> While <code>#pragma once</code> is available in most modern compilers, its implementation is tricky and might not always be reliable.


==Example==
==Example==
Line 72: Line 73:
| [[Clang]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://clang.llvm.org/doxygen/Pragma_8cpp-source.html#l00184 |title=clang: clang: Pragma.cpp Source File |publisher=Clang.llvm.org |accessdate=2013-08-19 |url-status=dead |archiveurl=https://web.archive.org/web/20140404052351/http://clang.llvm.org/doxygen/Pragma_8cpp-source.html#l00184 |archivedate=2014-04-04 }}</ref>
| [[Clang]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://clang.llvm.org/doxygen/Pragma_8cpp-source.html#l00184 |title=clang: clang: Pragma.cpp Source File |publisher=Clang.llvm.org |accessdate=2013-08-19 |url-status=dead |archiveurl=https://web.archive.org/web/20140404052351/http://clang.llvm.org/doxygen/Pragma_8cpp-source.html#l00184 |archivedate=2014-04-04 }}</ref>
|-
|-
| [[Comeau C/C++]] || {{Yes|style=text-align:left}}<ref>{{cite web| url=http://www.comeaucomputing.com/4.0/docs/userman/pragma.html |title=Comeau C++ Pre-Release User Documentation: Pragmas |publisher=Comeaucomputing.com |date= |accessdate=2013-08-19| url-status=dead}}{{dead link| date=September 2020}}</ref>
| [[Comeau C/C++]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://www.comeaucomputing.com/4.0/docs/userman/pragma.html |title=Comeau C++ Pre-Release User Documentation: Pragmas |publisher=Comeaucomputing.com |date= |accessdate=2013-08-19 |url-status=dead |archive-date=2013-12-11 |archive-url=https://web.archive.org/web/20131211122659/http://www.comeaucomputing.com/4.0/docs/userman/pragma.html }}</ref>
|-
|-
| [[Cray]] C and C++ || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://pubs.cray.com/content/S-5212/9.0/cray-compiling-environment-cce-release-overview/cce-900-release-overview-introduction |title=CCE 9.0.0 Release Overview Introduction S-5212 |publisher=Cray Inc. |date=2019-06-01 |accessdate=2019-09-23 }}</ref> (since 9.0)
| [[Cray]] C and C++ || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://pubs.cray.com/content/S-5212/9.0/cray-compiling-environment-cce-release-overview/cce-900-release-overview-introduction |title=CCE 9.0.0 Release Overview Introduction S-5212 |publisher=Cray Inc. |date=2019-06-01 |accessdate=2019-09-23 }}</ref> (since 9.0)
|-
|-
| [[C++Builder XE3]] || {{Yes|style=text-align:left}}<ref>{{cite web| url=http://docwiki.embarcadero.com/RADStudio/XE3/en/Pragma_once |title=#pragma once - RAD Studio XE3 |publisher=Docwiki.embarcadero.com |date=2010-12-02 |accessdate=2013-08-19}}</ref>
| [[C++Builder]] || {{Yes|style=text-align:left}}<ref>{{cite web| url=http://docwiki.embarcadero.com/RADStudio/XE3/en/Pragma_once |title=#pragma once - RAD Studio XE3 |publisher=Docwiki.embarcadero.com |date=2010-12-02 |accessdate=2013-08-19}}</ref> (since XE3. classic compiler only.)
|-
|-
| [[Digital Mars C++]] || {{Yes|style=text-align:left}}<ref>{{cite web| url=http://www.digitalmars.com/ctg/pragmas.html#once |title=Pragmas |publisher=Digital Mars |date= |accessdate=2013-08-19}}</ref>
| [[Digital Mars C++]] || {{Yes|style=text-align:left}}<ref>{{cite web| url=http://www.digitalmars.com/ctg/pragmas.html#once |title=Pragmas |publisher=Digital Mars |date= |accessdate=2013-08-19}}</ref>
Line 88: Line 89:
| [[Intel C++ Compiler]] || {{Yes|style=text-align:left}}<ref>{{cite web |title=Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead. |url=http://software.intel.com/en-us/articles/cdiag1782#comment-9466|work=Intel Developer Zones |accessdate=4 December 2013 |url-status=dead |archive-url=https://web.archive.org/web/20120131174333/http://software.intel.com/en-us/articles/cdiag1782/#comment-9466 |archive-date=31 January 2012 |quote=#pragma once should continue to work (Currently NOT deprecated) with the Intel Compiler.}}</ref>
| [[Intel C++ Compiler]] || {{Yes|style=text-align:left}}<ref>{{cite web |title=Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead. |url=http://software.intel.com/en-us/articles/cdiag1782#comment-9466|work=Intel Developer Zones |accessdate=4 December 2013 |url-status=dead |archive-url=https://web.archive.org/web/20120131174333/http://software.intel.com/en-us/articles/cdiag1782/#comment-9466 |archive-date=31 January 2012 |quote=#pragma once should continue to work (Currently NOT deprecated) with the Intel Compiler.}}</ref>
|-
|-
| [[Microsoft Visual C++]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://msdn.microsoft.com/en-us/library/4141z1cx%28v=vs.71%29.aspx |title=once (C/C++) |publisher=Msdn.microsoft.com |date= |accessdate=2013-08-19 |archive-url=https://web.archive.org/web/20160810031340/https://msdn.microsoft.com/en-us/library/4141z1cx(v=vs.71).aspx |archive-date=2016-08-10}}</ref><ref>{{cite web |url=https://msdn.microsoft.com/en-us/library/4141z1cx.aspx |title = once pragma {{!}} Microsoft Docs}}</ref> (since 4.2)
| [[Microsoft Visual C++]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://msdn.microsoft.com/en-us/library/4141z1cx%28v=vs.71%29.aspx |title=once (C/C++) |publisher=Microsoft Developer Network |date= |accessdate=2013-08-19 |archive-url=https://web.archive.org/web/20160810031340/https://msdn.microsoft.com/en-us/library/4141z1cx(v=vs.71).aspx |archive-date=2016-08-10}}</ref><ref>{{cite web |url=https://msdn.microsoft.com/en-us/library/4141z1cx.aspx |title = once pragma {{!}} Microsoft Docs| date=3 August 2021 }}</ref> (since 4.2)
|-
|-
|[[NVIDIA CUDA Compiler]]
|[[NVIDIA CUDA Compiler]]
Line 97: Line 98:
| [[ARM DS-5]] || {{Yes|style=text-align:left}}<ref>{{cite web|url=http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/BCFFDHJH.html |title=ARM Information Center |publisher=ARM |date= |accessdate=2013-12-17}}</ref>
| [[ARM DS-5]] || {{Yes|style=text-align:left}}<ref>{{cite web|url=http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/BCFFDHJH.html |title=ARM Information Center |publisher=ARM |date= |accessdate=2013-12-17}}</ref>
|-
|-
| [[IAR Systems|IAR C/C++]] || {{Yes|style=text-align:left}}<ref>Supported but not yet documented (doc planned for spring 2022)</ref>
| [[IAR Systems|IAR C/C++]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://wwwfiles.iar.com/arm/webic/doc/EWARM_DevelopmentGuide.ENU.pdf |title=IAR C/C++ DevelopmentGuide |publisher=IAR SYSTEMS |accessdate=1 March 2023}}</ref>
|-
|-
| [[Arm_Ltd.|Arm Keil Microcontroller Tools: C/C++ compilers]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://www.keil.com/support/man/docs/armcc/armcc_chr1359124215328.htm |title=Pragmas recognized by the compiler |publisher=Keil}}</ref> (e.g. KEIL ARMCC 5)
| [[Arm Ltd.|Arm Keil Microcontroller Tools: C/C++ compilers]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://www.keil.com/support/man/docs/armcc/armcc_chr1359124215328.htm |title=Pragmas recognized by the compiler |publisher=Keil}}</ref> (e.g. KEIL ARMCC 5)
|-
| [[OpenWatcom]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://github.com/open-watcom/open-watcom-v2/issues/714 |title=#pragma once does not work if files referenced by alternate paths |website=[[GitHub]] |quote="Now it should be fixed in git repository."}}</ref>
|-
|-
| [[Oracle Solaris Studio|Oracle Developer Studio C/C++]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://docs.oracle.com/cd/E60778_01/html/E68116/gqexw.html#OSGCCgqexp |title=Oracle® Developer Studio 12.5: GCC Compatibility Guide |last= |first= |date= |website= |publisher=Oracle |accessdate=2016-07-26}}</ref> (since 12.5)
| [[Oracle Solaris Studio|Oracle Developer Studio C/C++]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://docs.oracle.com/cd/E60778_01/html/E68116/gqexw.html#OSGCCgqexp |title=Oracle® Developer Studio 12.5: GCC Compatibility Guide |last= |first= |date= |website= |publisher=Oracle |accessdate=2016-07-26}}</ref> (since 12.5)
Line 106: Line 109:
|-
|-
| [[Tiny C Compiler|TinyCC]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://repo.or.cz/tinycc.git/commitdiff/b08ce880822875d4bef103719179501d6ba38730 |title=TinyCC pragma once implementation |accessdate=19 June 2018}}</ref> (since April 2015)
| [[Tiny C Compiler|TinyCC]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=http://repo.or.cz/tinycc.git/commitdiff/b08ce880822875d4bef103719179501d6ba38730 |title=TinyCC pragma once implementation |accessdate=19 June 2018}}</ref> (since April 2015)
|-
| [[Small Device C Compiler|SDCC]] || {{Yes |style=text-align:left}}<ref>{{cite web |url=https://sourceforge.net/p/sdcc/code/HEAD/tree/tags/sdcc-4.3.0/sdcc/support/cpp/libcpp/directives.cc |title=Implematation of SDCC pragma parsing, line 122 declaration, line 1393 registration |accessdate=2024-10-21}}</ref>(still Undocumented<ref>{{cite web |url=https://sdcc.sourceforge.net/doc/sdccman.pdf |title=SDCC Compiler User Guide section 3.16, page 62 |accessdate=21 Oct 2024}}</ref> Oct 2024)
|-
|-
| [[TASKING|TASKING VX-toolset for TriCore: C Compiler]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://www.tasking.com/support/tricore/ctc_user_guide_v6.2r2.pdf |title=MA160-800 (v6.2r2) March 13, 2018 page 92}}</ref> (since v6.2r2)
| [[TASKING|TASKING VX-toolset for TriCore: C Compiler]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://www.tasking.com/support/tricore/ctc_user_guide_v6.2r2.pdf |title=MA160-800 (v6.2r2) March 13, 2018 page 92}}</ref> (since v6.2r2)
|-
|-
| [[Texas Instruments|Texas Instruments Code Generation Tools: C Compiler]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://sir.ext.ti.com/jira/browse/EXT_EP-8185 |title=Texas Instruments - Embedded Software & Tools [EXT_EP-8185] Document #pragma once - Software Issue Report (SIR)}}</ref> (e.g. MSP430, ARM, C2000)
| [[Texas Instruments|Texas Instruments Code Generation Tools: C Compiler]] || {{Yes|style=text-align:left}}<ref>{{cite web |url=https://sir.ext.ti.com/jira/browse/EXT_EP-8185 |publisher=Software Issue Report - Texas Instruments |work=Embedded Software & Tools |title=[EXT_EP-8185] Document #pragma once |url-status=live |archive-url=https://web.archive.org/web/20220129024318/https://sir.ext.ti.com/jira/browse/EXT_EP-8185 |archive-date= Jan 29, 2022 }}</ref> (e.g. MSP430, ARM, C2000)
|}
|}



Latest revision as of 15:39, 13 December 2024

In the C and C++ programming languages, #pragma once is a non-standard but widely supported preprocessor directive designed to cause the current header file to be included only once in a single compilation.[1] Thus, #pragma once serves the same purpose as #include guards, but with several advantages, including less code, avoidance of name clashes, and sometimes improvement in compilation speed.[2] While #pragma once is available in most modern compilers, its implementation is tricky and might not always be reliable.

Example

[edit]
File "grandparent.h"
#pragma once

struct foo 
{
    int member;
};
File "parent.h"
#include "grandparent.h"
File "child.c"
#include "grandparent.h"
#include "parent.h"

In this example, the inclusion of grandparent.h in both parent.h and child.c would ordinarily cause a compilation error, because a struct with a given name can only be defined a single time in a given compilation. The #pragma once directive serves to avoid this by ignoring subsequent inclusions of grandparent.h.

Advantages

[edit]

Using #pragma once allows the C preprocessor to include a header file when it is needed and to ignore an #include directive otherwise. This has the effect of altering the behavior of the C preprocessor itself, and allows programmers to express file dependencies in a simple fashion, obviating the need for manual management.

The most common alternative to #pragma once is to use #define to set an #include guard macro, the name of which is picked by the programmer to be unique to that file. For example,

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

This approach minimally ensures that the contents of the include file are not seen more than once. This is more verbose, requires greater manual intervention, and is prone to programmer error as there are no mechanisms available to the compiler for prevention of accidental use of the same macro name in more than one file, which would result in only one of the files being included. Such errors are unlikely to remain undetected but can complicate the interpretation of a compiler error report. Since the pre-processor itself is responsible for handling #pragma once, the programmer cannot make errors which cause name clashes.

In the absence of #include guards around #include directives, the use of #pragma once will improve compilation speed for some compilers since it is a higher-level mechanism; the compiler itself can compare filenames or inodes without having to invoke the C preprocessor to scan the header for #ifndef and #endif. Yet, since include guards appear very often and the overhead of opening files is significant, it is common for compilers to optimize the handling of include guards, making them as fast as #pragma once.[3][4][5]

Caveats

[edit]

Identifying the same file on a file system is not a trivial task.[6] Symbolic links and especially hard links may cause the same file to be found under different names in different directories. Compilers may use a heuristic that compares file size, modification time and content.[7] Additionally, #pragma once can do the wrong thing if the same file is intentionally copied into several parts of a project, e.g. when preparing the build. Whereas include guards would still protect from double definitions, #pragma once may or may not treat them as the same file in a compiler-dependent way. These difficulties, together with difficulties related to defining what constitutes the same file in the presence of hard links, networked file systems, etc. has so far prevented the standardization of #pragma once.[citation needed]

The use of #include guard macros allows dependent code to recognize and respond to slight differences in semantics or interfaces of competing alternatives. For example,

#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

In this case, the direct determination for which API is available would make use of the fact that the include file had advertised itself with its #include guard macro.

The #include directive is defined to represent a programmer's intention to actually include the text of a file at the point of the directive. This may occur several times within a single compilation unit, and is useful for evaluating macro-containing contents multiple times against changing definitions of the macro.

The use of #pragma once, like the use of #include guard macros within an include file places the responsibility upon its authors in order to protect against undesired multiple inclusion. Over-reliance upon either mechanism on the part of programmers by direct, unprotected use of #include directives without their own #include guard will lead to failure when using an include file that has not protected itself with either mechanism.

Portability

[edit]
Compiler Support
Clang Yes[8]
Comeau C/C++ Yes[9]
Cray C and C++ Yes[10] (since 9.0)
C++Builder Yes[11] (since XE3. classic compiler only.)
Digital Mars C++ Yes[12]
GNU Compiler Collection (GCC) Yes[13] (officially since 3.4[6][14])
HP C/aC++ Yes[15] (since at least A.06.12)
IBM XL C/C++ Yes[16] (since 13.1.1)
Intel C++ Compiler Yes[17]
Microsoft Visual C++ Yes[18][19] (since 4.2)
NVIDIA CUDA Compiler Yes (depending on the underlying host compiler)
Pelles C Yes[20]
ARM DS-5 Yes[21]
IAR C/C++ Yes[22]
Arm Keil Microcontroller Tools: C/C++ compilers Yes[23] (e.g. KEIL ARMCC 5)
OpenWatcom Yes[24]
Oracle Developer Studio C/C++ Yes[25] (since 12.5)
Portland Group C/C++ Yes[26] (since at least 17.4)
TinyCC Yes[27] (since April 2015)
SDCC Yes[28](still Undocumented[29] Oct 2024)
TASKING VX-toolset for TriCore: C Compiler Yes[30] (since v6.2r2)
Texas Instruments Code Generation Tools: C Compiler Yes[31] (e.g. MSP430, ARM, C2000)

References

[edit]
  1. ^ "once". Microsoft Docs. 3 November 2016. Retrieved 25 July 2019.
  2. ^ "Games from Within: Even More Experiments with Includes". 2005-01-25. Archived from the original on September 30, 2008. Retrieved 2013-08-19.
  3. ^ "The C Preprocessor: 1. The C Preprocessor". Gcc.gnu.org. 1996-02-01. Retrieved 2013-08-19.
  4. ^ ""Clang" CFE Internals Manual — Clang 3.4 documentation". Clang.llvm.org. Retrieved 2013-08-19.
  5. ^ "clang: File manipulation routines". Clang.llvm.org. Retrieved 2013-08-19.
  6. ^ a b "GCC 3.4 Release Series — Changes, New Features, and Fixes". Gcc.gnu.org. Retrieved 2013-08-19.
  7. ^ "should_stack_file() function in GCC source code".
  8. ^ "clang: clang: Pragma.cpp Source File". Clang.llvm.org. Archived from the original on 2014-04-04. Retrieved 2013-08-19.
  9. ^ "Comeau C++ Pre-Release User Documentation: Pragmas". Comeaucomputing.com. Archived from the original on 2013-12-11. Retrieved 2013-08-19.
  10. ^ "CCE 9.0.0 Release Overview Introduction S-5212". Cray Inc. 2019-06-01. Retrieved 2019-09-23.
  11. ^ "#pragma once - RAD Studio XE3". Docwiki.embarcadero.com. 2010-12-02. Retrieved 2013-08-19.
  12. ^ "Pragmas". Digital Mars. Retrieved 2013-08-19.
  13. ^ "Alternatives to Wrapper #ifndef". Gcc.gnu.org. Retrieved 2013-08-20.
  14. ^ "GCC Bug 11569 - there's no substitute for #pragma once". 2003-07-18. Retrieved 2020-10-21.
  15. ^ "HP aC++/HP C A.06.29 Programmer's Guide; March 2016 (AR1603)".
  16. ^ "GCC pragmas". IBM. Retrieved 2015-02-20.
  17. ^ "Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead". Intel Developer Zones. Archived from the original on 31 January 2012. Retrieved 4 December 2013. #pragma once should continue to work (Currently NOT deprecated) with the Intel Compiler.
  18. ^ "once (C/C++)". Microsoft Developer Network. Archived from the original on 2016-08-10. Retrieved 2013-08-19.
  19. ^ "once pragma | Microsoft Docs". 3 August 2021.
  20. ^ IDE help/documentation
  21. ^ "ARM Information Center". ARM. Retrieved 2013-12-17.
  22. ^ "IAR C/C++ DevelopmentGuide" (PDF). IAR SYSTEMS. Retrieved 1 March 2023.
  23. ^ "Pragmas recognized by the compiler". Keil.
  24. ^ "#pragma once does not work if files referenced by alternate paths". GitHub. Now it should be fixed in git repository.
  25. ^ "Oracle® Developer Studio 12.5: GCC Compatibility Guide". Oracle. Retrieved 2016-07-26.
  26. ^ "The Portland Group". Retrieved 31 July 2016.
  27. ^ "TinyCC pragma once implementation". Retrieved 19 June 2018.
  28. ^ "Implematation of SDCC pragma parsing, line 122 declaration, line 1393 registration". Retrieved 2024-10-21.
  29. ^ "SDCC Compiler User Guide section 3.16, page 62" (PDF). Retrieved 21 Oct 2024.
  30. ^ "MA160-800 (v6.2r2) March 13, 2018 page 92" (PDF).
  31. ^ "[EXT_EP-8185] Document #pragma once". Embedded Software & Tools. Software Issue Report - Texas Instruments. Archived from the original on Jan 29, 2022.
[edit]