原文: https://en.wikipedia.org/wiki/Pragma_once#cite_note-11
#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]
#pragma once
struct foo
{
int member;
};
#include "grandparent.h"
#include "grandparent.h"
#include "parent.h"
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]
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.
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] |
|title=
(help)=====================笔记======================
原来以为 #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++; }