#ifndef三件套与#pragma once

注:未经博主同意,不得转载。

为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式。在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。
    方式一:

1 #ifndef __SOMEFILE_H__
2 #define __SOMEFILE_H__
3      // ... ...
4      // 一些声明语句
5 #endif

方式二:

#pragma once
    ... ... // 一些声明语句

  #ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况——这种情况有时非常让人抓狂。
  #pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
  #pragma once方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受语言天生的支持,不受编译器的任何限制;而#pragma once方式却不受一些较老版本的编译器支持,换言之,它的兼容性不够好。也许,再过几年等旧的编译器死绝了,这就不是什么问题了。
  我还看到一种用法是把两者放在一起的:

1     #pragma once
2     #ifndef __SOMEFILE_H__
3     #define __SOMEFILE_H__
4     //... ...
5     // 一些声明语句
6     #endif

  看起来似乎是想兼有两者的优点。不过只要使用了#ifndef就会有宏名冲突的危险,所以混用两种方法似乎不能带来更多的好处,倒是会让一些不熟悉的人感到困惑。

  选择哪种方式,应该在了解两种方式的情况下,视具体情况而定。事实上,只要有一个合理的约定来避开缺点,我认为哪种方式都是可以接受的。而这个已经不是标准或者编译器的责任了,应当由程序员来搞定。

时间: 2024-10-25 16:29:41

#ifndef三件套与#pragma once的相关文章

#pragma once与 #ifndef的区别

? 为了避免同一个文件被include多次 1???#ifndef方式2???#pragma once方式 在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别.????方式一: ??? #ifndef __SOMEFILE_H__??? #define __SOMEFILE_H__??? ... ... // 一些声明语句??? #endif ????方式二: ??? #pragma once??? ... ... // 一些声明语句 ??? #ifndef的

# program once 用途 及与 ifndef使用异同(转载)

在头文件中用这种写法就是为了该头文件被重复包含时不会出现符合重定义的错误. 效果等同于     #ifndef __xxx__     #define __xxx__     ...    #endif // __xxx__ 详细如下: #pragma once和ifndef使用异同为了避免同一个文件被include多次1   #ifndef方式2   #pragma once方式在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别.       方式一: #i

# program once 用途 及与 ifndef使用异同

在头文件中用这种写法就是为了该头文件被重复包含时不会出现符合重定义的错误. 效果等同于     #ifndef __xxx__     #define __xxx__     ...    #endif // __xxx__ 详细如下: #pragma once和ifndef使用异同为了避免同一个文件被include多次1   #ifndef方式2   #pragma once方式在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别.       方式一: #i

[泛型]队列,栈,简单双向队列的实现

写了个栈和队列以及简化的deque模版. Stack: 1 #ifndef _KIRAI_STACK 2 #pragma once 3 4 #include <cstdlib> 5 6 namespace kirai { 7 template <class Type> 8 struct Node { 9 typedef Node<Type>* NP; 10 Type data; 11 NP pre; 12 Node<Type>() { pre = NULL;

dm9000c 移值新内核 linux-4.1.24

错误 1 /home/dm9000/dm9dev9000c.c:309: error: conflicting types for 'phy_read'include/linux/phy.h:637: error: previous definition of 'phy_read' was here/home/dm9000/dm9dev9000c.c:310: error: conflicting types for 'phy_write'include/linux/phy.h:652: err

C++预处理和头文件保护符

一预处理 1.常见的预处理功能 预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译.布局控制和宏替换4种.文件包含:#include 是一种最为常见的预处理,主要是做为文件的引用组合源程序正文.条件编译:#if,#ifndef,#ifdef,#endif,#undef等也是比较常见的预处理,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制.防止对文件重复包含的功能.布局控制:#pragma,这也是我们应用预处理的一个重要

UVa 227 / UVALive 5166 Puzzle 谜题 (结构体)

Puzzle Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Description   A children's puzzle that was popular 30 years ago consisted of a 5x5 frame which contained 24 small squares of equal size. A unique letter of the alphabet

S3C2440实现dm9000网卡驱动程序移植

20150419 S3C2440实现dm9000网卡驱动程序移植 2015-04-19 Lover雪儿 首先附上厂家提供的完整的dm9000程序: 1 /* 2 3 dm9ks.c: Version 2.08 2007/02/12 4 5 A Davicom DM9000/DM9010 ISA NIC fast Ethernet driver for Linux. 6 7 This program is free software; you can redistribute it and/or

一个C&amp;C++程序的生命历程

翻了好多博客,内容星星点点,没找到我想要的,现在吸取大神精华,加上本人拙见,总结如下: 一个C或C++程序从你开始编写,到结束,整个过程,都做了些什么,请看下文: 先看大体的过程:看图: 我在这里主要想说的就是,程序到这每个阶段都干了什么,这个有时候很重要,举个例子: #define BSC // #define BMC /* #define EMC */ //1.双斜杠注释 BSC lining is a goog boy //2./**/注释 BMC lining is good boy E