Pragma once

Last updated

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] On the other hand, #pragma once is not necessarily available in all compilers and its implementation is tricky and might not always be reliable.

Contents

Example

File "grandparent.h"
#pragma oncestructfoo{intmember;};
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

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...contentsofgrandparent.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

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...useoneknownAPI#elif defined TLS_B_H...useanotherknownAPI#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

CompilerSupport
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)
TASKING VX-toolset for TriCore: C Compiler Yes [28] (since v6.2r2)
Texas Instruments Code Generation Tools: C Compiler Yes [29] (e.g. MSP430, ARM, C2000)

Related Research Articles

ANSI C, ISO C, and Standard C are successive standards for the C programming language published by the American National Standards Institute (ANSI) and ISO/IEC JTC 1/SC 22/WG 14 of the International Organization for Standardization (ISO) and the International Electrotechnical Commission (IEC). Historically, the names referred specifically to the original and best-supported version of the standard. Software developers writing in C are encouraged to conform to the standards, as doing so helps portability between compilers.

<span class="mw-page-title-main">Transclusion</span> Including one data set inside another automatically

In computer science, transclusion is the inclusion of part or all of an electronic document into one or more other documents by reference via hypertext. Transclusion is usually performed when the referencing document is displayed, and is normally automatic and transparent to the end user. The result of transclusion is a single integrated document made of parts assembled dynamically from separate sources, possibly stored on different computers in disparate places.

<span class="mw-page-title-main">Single instruction, multiple data</span> Type of parallel processing

Single instruction, multiple data (SIMD) is a type of parallel processing in Flynn's taxonomy. SIMD can be internal and it can be directly accessible through an instruction set architecture (ISA), but it should not be confused with an ISA. SIMD describes computers with multiple processing elements that perform the same operation on multiple data points simultaneously.

The C preprocessor is the macro preprocessor for several computer programming languages, such as C, Objective-C, C++, and a variety of Fortran languages. The preprocessor provides inclusion of header files, macro expansions, conditional compilation, and line control.

<span class="mw-page-title-main">OpenMP</span> Open standard for parallelizing

OpenMP is an application programming interface (API) that supports multi-platform shared-memory multiprocessing programming in C, C++, and Fortran, on many platforms, instruction-set architectures and operating systems, including Solaris, AIX, FreeBSD, HP-UX, Linux, macOS, and Windows. It consists of a set of compiler directives, library routines, and environment variables that influence run-time behavior.

In the C and C++ programming languages, an inline function is one qualified with the keyword inline; this serves two purposes:

  1. It serves as a compiler directive that suggests that the compiler substitute the body of the function inline by performing inline expansion, i.e. by inserting the function code at the address of each function call, thereby saving the overhead of a function call. In this respect it is analogous to the register storage class specifier, which similarly provides an optimization hint.
  2. The second purpose of inline is to change linkage behavior; the details of this are complicated. This is necessary due to the C/C++ separate compilation + linkage model, specifically because the definition (body) of the function must be duplicated in all translation units where it is used, to allow inlining during compiling, which, if the function has external linkage, causes a collision during linking. C and C++ resolve this in different ways.
<span class="mw-page-title-main">C99</span> C programming language standard, 1999 revision

C99 is an informal name for ISO/IEC 9899:1999, a past version of the C programming language standard. It extends the previous version (C90) with new features for the language and the standard library, and helps implementations make better use of available computer hardware, such as IEEE 754-1985 floating-point arithmetic, and compiler technology. The C11 version of the C programming language standard, published in 2011, updates C99.

<span class="mw-page-title-main">LLVM</span> Compiler backend for multiple programming languages

LLVM is a set of compiler and toolchain technologies that can be used to develop a frontend for any programming language and a backend for any instruction set architecture. LLVM is designed around a language-independent intermediate representation (IR) that serves as a portable, high-level assembly language that can be optimized with a variety of transformations over multiple passes. The name LLVM originally stood for Low Level Virtual Machine, though the project has expanded and the name is no longer officially an initialism.

A variadic macro is a feature of some computer programming languages, especially the C preprocessor, whereby a macro may be declared to accept a varying number of arguments.

In computer programming, a directive or pragma is a language construct that specifies how a compiler should process its input. Depending on the programming language, directives may or may not be part of the grammar of the language and may vary from compiler to compiler. They can be processed by a preprocessor to specify compiler behavior, or function as a form of in-band parameterization.

In the C and C++ programming languages, an #include guard, sometimes called a macro guard, header guard or file guard, is a particular construct used to avoid the problem of double inclusion when dealing with the include directive.

In computer programming, a precompiled header (PCH) is a header file that is compiled into an intermediate form that is faster to process for the compiler. Usage of precompiled headers may significantly reduce compilation time, especially when applied to large header files, header files that include many other header files, or header files that are included in many translation units.

In computer programming, boilerplate code, or simply boilerplate, are sections of code that are repeated in multiple places with little to no variation. When using languages that are considered verbose, the programmer must write a lot of boilerplate code to accomplish only minor functionality.

A weak symbol denotes a specially annotated symbol during linking of Executable and Linkable Format (ELF) object files. By default, without any annotation, a symbol in an object file is strong. During linking, a strong symbol can override a weak symbol of the same name. In contrast, in the presence of two strong symbols by the same name, the linker resolves the symbol in favor of the first one found. This behavior allows an executable to override standard library functions, such as malloc(3). When linking a binary executable, a weakly declared symbol does not need a definition. In comparison, a declared strong symbol without a definition triggers an undefined symbol link error.

The Windows software trace preprocessor is a preprocessor that simplifies the use of WMI event tracing to implement efficient software tracing in drivers and applications that target Windows 2000 and later operating systems. WPP was created by Microsoft and is included in the Windows DDK. Although WPP is wide in its applicability, it is not included in the Windows SDK, and therefore is primarily used for drivers and driver support software produced by software vendors that purchase the Windows DDK.

Clang is a compiler front end for the C, C++, Objective-C, and Objective-C++ programming languages, as well as the OpenMP, OpenCL, RenderScript, CUDA, SYCL, and HIP frameworks. It acts as a drop-in replacement for the GNU Compiler Collection (GCC), supporting most of its compilation flags and unofficial language extensions. It includes a static analyzer, and several code analysis tools.

In C and C++ programming language terminology, a translation unit is the ultimate input to a C or C++ compiler from which an object file is generated. A translation unit roughly consists of a source file after it has been processed by the C preprocessor, meaning that header files listed in #include directives are literally included, sections of code within #ifndef may be included, and macros have been expanded.

Many programming languages and other computer files have a directive, often called include, import, or copy, that causes the contents of the specified file to be inserted into the original file. These included files are called header files or copybooks. They are often used to define the physical layout of program data, pieces of procedural code, and/or forward declarations while promoting encapsulation and the reuse of code or data.

C++/CX(C++ component extensions) is a language projection for Microsoft's Windows Runtime platform. It takes the form of a language extension for C++ compilers, and it enables C++ programmers to write programs that call Windows Runtime (WinRT) APIs. C++/CX is superseded by the C++/WinRT language projection, which is not an extension to the C++ language; rather, it's an entirely standard modern ISO C++17 header-file-based library.

Objective-C is a high-level general-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language. Originally developed by Brad Cox and Tom Love in the early 1980s, it was selected by NeXT for its NeXTSTEP operating system. Due to Apple macOS’s direct lineage from NeXTSTEP, Objective-C was the standard programming language used, supported, and promoted by Apple for developing macOS and iOS applications until the introduction of the Swift programming language in 2014.

References

  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. 1 2 "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".
  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". 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. "MA160-800 (v6.2r2) March 13, 2018 page 92" (PDF).
  29. "[EXT_EP-8185] Document #pragma once". Embedded Software & Tools. Software Issue Report - Texas Instruments. Archived from the original on Jan 29, 2022.