#pragma once
在C和C++编程语言中,#pragma once是一个非标准但是被广泛支持的前置处理符号,会让所在的文件在一个单独的编译中只被包含一次。以此方式,#pragma once
提供类似include防范的目的,但是拥有较少的代码且能避免名称的碰撞。
示例
编辑请参考include防范里其中一种状况的示例或其他的使用方法。如下:
- grandparent.h
#pragma once
struct foo
{
int member;
};
- parent.h
#include "grandparent.h"
- child.c
#include "grandparent.h"
#include "parent.h"
优缺点
编辑使用#pragma once
代替include防范将加快编译速度,因为这是一种高阶的机制;编译器会自动比对文件名称或inode而不需要在头文件去判断#ifndef
和#endif
。
另一方面,部分编译器,例如GCC、clang等,也包含特别的代码来识别和有效率的管理include防范。因此使用#pragma once
并不会得到明显的加速。[1][2][3]
此外,因为编译器自己必须承担管理#pragma once
,它不必定义新的指令名称,例如在include防范文章示例的H_GRANDFATHER
。这能排除名称碰撞的风险,意思就是至少第一次包含头文件不会再有错误。
然而,这种高阶的管理有好也有坏;设计者必须依赖编译器正确的管理#pragma once
。编译器如果犯错,例如没有辨认出在相同文件中的两个不同符号链接名称指针,此时编译会错误。编译器对于#pragma once
可能包含相关的bug LCC-Win32 2004年[1][2]和GCC 1998年。[3](页面存档备份,存于互联网档案馆)2005年,GCC文件中将#pragma once
列为“已淘汰”的特性。[4](页面存档备份,存于互联网档案馆)随着gcc 3.4的发布,gcc解决了#pragma once中的一些问题(主要是跟符号链接和硬链接有关),并且去掉了#pragma once的“已淘汰”的标签。[5](页面存档备份,存于互联网档案馆)
编译器支持
编辑Compiler | #pragma once |
---|---|
Clang | 支持[4] |
Comeau C/C++ | 支持[5] |
C++Builder XE Seattle | 支持[6] |
Digital Mars C++ | 支持[7] |
GCC | 支持[8](3.4版本以后[9]) |
Intel C++编译器 | 支持[10] |
Microsoft Visual C++ | 支持[11] |
Pelles C | 支持[12] |
IAR C/C++ | 支持[13] (2022年以后[14]) |
TinyCC | 支持[15] (2015年以后) |
参考文献
编辑- ^ The C Preprocessor: 1. The C Preprocessor. Gcc.gnu.org. 1996-02-01 [2013-08-19]. (原始内容存档于2013-08-07).
- ^ “Clang”CFE Internals Manual—Clang 3.4 documentation. Clang.llvm.org. [2013-08-19]. (原始内容存档于2013-08-06).
- ^ clang: File manipulation routines. Clang.llvm.org. [2013-08-19]. (原始内容存档于2013-11-11).
- ^ clang: clang: Pragma.cpp Source File. Clang.llvm.org. [2013-08-19]. (原始内容存档于2014-04-04).
- ^ Comeau C++ Pre-Release User Documentation: Pragmas. Comeaucomputing.com. [2013-08-19]. (原始内容存档于2013-12-11).
- ^ #pragma once - RAD Studio XE Seattle. Docwiki.embarcadero.com. 2015-08-25 [2016-03-10]. (原始内容存档于2016-03-10).
- ^ Pragmas. Digital Mars. [2013-08-19]. (原始内容存档于2013-12-12).
- ^ Alternatives to Wrapper #ifndef. Gcc.gnu.org. [2013-08-20]. (原始内容存档于2016-03-04).
- ^ GCC 3.4 Release Series—Changes, New Features, and Fixes. Gcc.gnu.org. [2013-08-19]. (原始内容存档于2013-08-07).
- ^ Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead.. Intel Developer Zones. [4 December 2013]. (原始内容存档于2013-12-11).
- ^ once(C/C++). Msdn.microsoft.com. [2013-08-19]. (原始内容存档于2016-08-10).
- ^ IDE help/documentation
- ^ IAR C/C++ Development Guide (PDF). IAR Systems. [4 December 2013]. (原始内容 (PDF)存档于2017年5月16日).
- ^ Supported but not yet documented (doc planned for spring 2022)
- ^ TinyCC pragma once implementation. [19 June 2018]. (原始内容存档于2021-12-07).