#pragma once

原文: https://en.wikipedia.org/wiki/Pragma_once#cite_note-11


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]

Contents

  • 1Example
  • 2Advantages
  • 3Caveats
  • 4Portability
  • 5References

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 aninclude 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 orinodes without having to invoke theC preprocessor to scan the header for#ifndef and #endif. It is important to note that some compilers such asGCC,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 hard links may cause the same file to be found under different names. 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. Withinclude 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[12] (since at least A.06.12)
IBM XL C/C++ Supported[13] (since 13.1.1)
Intel C++ Compiler Supported[14]
Microsoft Visual C++ Supported[15]
Pelles C Supported[16]
ARM DS-5 Supported[17]
IAR C/C++ Supported[18]
Solaris Studio C/C++ Not supported[19][20]

References

  1. "Games from Within: Even More Experiments with Includes". Web.archive.org. 2005-01-25. Retrieved2013-08-19.
  2. "The C Preprocessor: 1. The C Preprocessor". Gcc.gnu.org. 1996-02-01. Retrieved 2013-08-19.
  3. ""Clang" CFE Internals Manual — Clang 3.4 documentation". Clang.llvm.org. Retrieved2013-08-19.
  4. "clang: File manipulation routines". Clang.llvm.org. Retrieved2013-08-19.
  5. "GCC 3.4 Release Series — Changes, New Features, and Fixes". Gcc.gnu.org. Retrieved 2013-08-19.
  6. "should_stack_file() function in GCC source code".
  7. "clang: clang: Pragma.cpp Source File". Clang.llvm.org. Retrieved 2013-08-19.
  8. "Comeau C++ Pre-Release User Documentation: Pragmas". Comeaucomputing.com. Retrieved 2013-08-19.
  9. "#pragma once - RAD Studio XE3". Docwiki.embarcadero.com. 2010-12-02. Retrieved 2013-08-19.
  10. "Pragmas". Digital Mars. Retrieved2013-08-19.
  11. "Alternatives to Wrapper #ifndef". Gcc.gnu.org. Retrieved2013-08-20.
  12. http://h20565.www2.hp.com/hpsc/doc/public/display?docId=emr_na-c02936807.Missing or empty |title= (help)
  13. "Supported GCC pragmas". IBM. Retrieved 2015-02-20.
  14. "Diagnostic 1782: #pragma once is obsolete. Use #ifndef guard instead.". Intel Developer Zones. Retrieved4 December 2013.
  15. "once (C/C++)". Msdn.microsoft.com. Retrieved 2013-08-19.
  16. IDE help/documentation
  17. "ARM Information Center". ARM. Retrieved 2013-12-17.
  18. "IAR C/C++ Development Guide"(PDF).IAR Systems. Retrieved4 December 2013.
  19. "Solaris Studio 12.4: C++ User's Guide". Oracle. Retrieved 2015-02-20.
  20. "Solaris Studio 12.4: C User's Guide". Oracle. Retrieved 2015-02-20.

=====================笔记======================

原来以为 #pragma once 只是windows平台支持,看完这个wiki,发现gcc也开始支持了。

优点是:

0、使用方便

不用再自己去写 #ifndef ... #define ... #endif

1、防止宏定义冲突

因为头文件的宏都是编码者自己定义的,所以有可能会造成宏定义冲突。

而#pragma once是编译器处理这些问题,不会出现冲突。

2、编译速度得到提升

只是对于某些编译器来说的。gcc编译器就几乎没有速度上的提升。


=====================关于c语言中的声明和定义的知识=====================

http://stackoverflow.com/questions/4769599/declaration-or-definition-in-c

对于内置类型的变量:

 Declaration Definition Tentative Definition Initialized int i; (inside a block) Yes Yes No No int i=5; (inside a block) Yes Yes No Yes(to 5) int i; (otherwise) Yes No Yes Yes(to 0) extern int i; Yes No No No All definitions are declarations but not vice-versa

一个编译单元中不能有结构体的重复定义。

不同编译单元之间可以有结构体的重复定义。

测试代码1:

// test.c

struct a
{
	int x;
};

// error: redefinition
//struct a
//{
//	int y;
//};

// ok
int b; // 声明
int b; // 声明

// ok
int c = 1; // 声明+定义
int c; // 声明

// ok
int d; // 声明
int d = 1; // 声明 + 定义

// error: redefinition
//int e = 1; // 声明+定义
//int e = 2; // 声明+定义

// ok
int f; // 声明
int f = 1; // 声明 + 定义



/* error
warning: data definition has no type or storage class
g = 2;
  ^
error: redefinition of ‘g’
note: previous definition of ‘g’ was here
   int g = 1;
*/
int g = 1; // 声明 + 定义
//g = 2;


//warning: data definition has no type or storage class
i = 5;

int sum()
{
	int c;
	//int c; // error : redefinition

	// ok
	int h = 1;
	h = 2;

	// ok
	i++;
}




你可能感兴趣的:(once,pragma)