pragma once
In the C and C++ programming languages, #pragma once is a non-standard but widely supported preprocessor directive designed to cause the current source file to be included only once in a single compilation. 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.[1]
Example
- File "grandparent.h"
#pragma once
struct foo
{
int member;
};
- File "parent.h"
#include "grandparent.h"
- File "child.c"
#include "grandparent.h"
#include "parent.h"
Advantages
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 is more complicated, possibly less efficient, and prone to error as there are no mechanisms to prevent a programmer accidentally using the same macro name in more than one file, which would result in only one of the files being included. This problem renders #pragma once
to be advantageous. Since the compiler itself is responsible for handling #pragma once
, the programmer cannot make errors which cause name clashes.
Using #pragma once
instead of include guards will, for some compilers, improve compilation speed 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
. It is important to note that some compilers such as GCC, Clang, and EDG-based compilers include specific optimizations to recognize and optimize the handling of include guards, and thus little or no speedup benefit is obtained from the use of #pragma once
.[2][3][4]
Caveats
Identifying the same file on a file system is not a trivial task.[5] 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.[6] This backfires when the same file is intentionally copied into several parts of a project. With include guard based on file path these copies would be treated differently while #pragma once
may arbitrarily treat them as the same file in a compiler-dependent way.
Portability
Compiler | #pragma once |
---|---|
Clang | Supported[7] |
Comeau C/C++ | Supported[8] |
C++Builder XE3 | Supported[9] |
Digital Mars C++ | Supported[10] |
GCC | Supported[11] (since 3.4[5]) |
HP C/aC++ | Supported (since at least A.06.12) |
IBM XL C/C++ | Supported[12] (since 13.1.1) |
Intel C++ Compiler | Supported[13] |
Microsoft Visual C++ | Supported[14] (since 4.2) |
Pelles C | Supported[15] |
ARM DS-5 | Supported[16] |
IAR C/C++ | Supported[17] |
Oracle Developer Studio C/C++ | Supported[18] (since 12.5) |
Portland Group C/C++ | Not supported[19] |
C/C++ Preprocessor Detector:[20]
/*checks for pragma once support*/
#if (defined(__SUNPRO_C)&&(__SUNPRO_C>=0x5140))||(defined(__SUNPRO_CC)&&(__SUNPRO_CC>=0x5140))
//Oracle Developer Studio C/C++ (12.5 or later)
# define _pragma_once_support 1
#elif defined(_MSC_VER)&&(_MSC_VER>=1020) //MSVC
# define _pragma_once_support 1
#elif defined(__clang__) //clang
# define _pragma_once_support 1
#elif defined(__COMO__) //comeau
# define _pragma_once_support 1
#elif defined(__CODEGEARC__)&&(__CODEGEARC__ >=650)
//C++Builder (XE3 or greater)
# define _pragma_once_support 1
#elif defined(__DMC__) //Digital Mars
# define _pragma_once_support 1
#elif defined(__GNUC__)&&((__GNUC__ >3)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==3)&&(__GNUC_MINOR__ >=4)))
//GCC
# define _pragma_once_support 1
#elif defined(__HP_aCC)&&(__HP_aCC >=61200)
//HP aC++ (A.06.12)
# define _pragma_once_support 1
#elif defined(__xlC__)&&((__xlC__ >1301)||((__xlC__ ==1301)&&(__xlC_ver__ >0100)))
//IBM
# define _pragma_once_support 1
#elif defined(__INTEL_COMPILER)||defined(__ICC)||defined(__ECC)||defined(__ICL)
//intel
# define _pragma_once_support 1
#elif defined(__POCC__) //Pelles C
# define _pragma_once_support 1
#elif defined(__CC_ARM) //ARM compiler
# define _pragma_once_support 1
#elif defined(__IAR_SYSTEMS_ICC__) //IAR C/C++
# define _pragma_once_support 1
#elif defined(__PGI) //Portland Group C/C++
# define _pragma_once_support 0
#endif
Usage:
/*if pragma once support then use it in addition to include guard*/
#if defined(_pragma_once_support)
# pragma once
#endif
References
- ↑ "Games from Within: Even More Experiments with Includes". Web.archive.org. 2005-01-25. Archived from the original on September 30, 2008. Retrieved 2013-08-19.
- ↑ "The C Preprocessor: 1. The C Preprocessor". Gcc.gnu.org. 1996-02-01. Retrieved 2013-08-19.
- ↑ ""Clang" CFE Internals Manual — Clang 3.4 documentation". Clang.llvm.org. Retrieved 2013-08-19.
- ↑ "clang: File manipulation routines". Clang.llvm.org. Retrieved 2013-08-19.
- 1 2 "GCC 3.4 Release Series — Changes, New Features, and Fixes". Gcc.gnu.org. Retrieved 2013-08-19.
- ↑ "should_stack_file() function in GCC source code".
- ↑ "clang: clang: Pragma.cpp Source File". Clang.llvm.org. Retrieved 2013-08-19.
- ↑ "Comeau C++ Pre-Release User Documentation: Pragmas". Comeaucomputing.com. Retrieved 2013-08-19.
- ↑ "#pragma once - RAD Studio XE3". Docwiki.embarcadero.com. 2010-12-02. Retrieved 2013-08-19.
- ↑ "Pragmas". Digital Mars. Retrieved 2013-08-19.
- ↑ "Alternatives to Wrapper #ifndef". Gcc.gnu.org. Retrieved 2013-08-20.
- ↑ "Supported GCC pragmas". IBM. Retrieved 2015-02-20.
- ↑ "Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead.". Intel Developer Zones. Retrieved 4 December 2013.
- ↑ "once (C/C++)". Msdn.microsoft.com. Retrieved 2013-08-19.
- ↑ IDE help/documentation
- ↑ "ARM Information Center". ARM. Retrieved 2013-12-17.
- ↑ "IAR C/C++ Development Guide" (PDF). IAR Systems. Retrieved 4 December 2013.
- ↑ "Oracle® Developer Studio 12.5: GCC Compatibility Guide". Oracle. Retrieved 2016-07-26.
- ↑ "The Portland Group". Retrieved 31 July 2016.
- ↑ "C/C++ Preprocessor Detector".