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

不同的地方

// 方式一:
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
... ... // 声明、定义语句
#endif //方式二:
#pragma once
... ... // 声明、定义语句

  

#ifndef的方式受C/C++语言标准支持。它不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包含。当然,缺点就是如果不同头文件中的宏名不小心“撞车”,可能就会导致你看到头文件明明存在,编译器却硬说找不到声明的状况——这种情况有时非常让人抓狂。由于编译器每次都需要打开头文件才能判定是否有重复定义,因此在编译大型项目时,ifndef会使得编译时间相对较长,因此一些编译器逐渐开始支持#pragma once的方式。

#pragma once一般由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。你无法对一个头文件中的一段代码作pragma once声明,而只能针对文件。
其好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。大型项目的编译速度也因此提高了一些。
对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,这种重复包含很容易被发现并修正。

关于选择
#pragma once方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受C/C++语言标准的支持,不受编译器的任何限制;而#pragma once方式却不受一些较老版本的编译器支持,一些支持了的编译器又打算去掉它,所以它的兼容性可能不够好。一般而言,当程序员听到这样的话,都会选择#ifndef方式,为了努力使得自己的代码“存活”时间更久,通常宁愿降低一些编译性能,这是程序员的个性,当然这是题外话啦。 还看到一种用法是把两者放在一起的:

  

#pragma once
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
... ... // 声明、定义语句
#endif

  

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

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

btw:我看到GNU的一些讨论似乎是打算在GCC 3.4(及其以后?)的版本取消对#pragma once的支持。不过事实上,我手上的GCC 3.4.2和GCC 4.1.1仍然支持#pragma once,甚至没有deprecation warning,倒是GCC2.95会对#pragma once提出warning。
    VC6及其以后版本亦提供对#pragma once方式的支持,这一特性应该基本稳定下来了。

[转]避免头文件重复包含以及#ifndef 与 #program once 的区别的更多相关文章

  1. C/C++避免头文件重复包含的方法

    C/C++避免头文件重复包含的方法 1. #ifndef 2. #pragma once 3. 混合使用 在实际的编程过程中,因为会使用多个文件,所以在文件中不可避免的要引入一些头文件,这样就可能会出 ...

  2. C:防止头文件重复包含

    当一个项目比较大时,往往都是分文件,这时候有可能不小心把同一个头文件 include 多次,或者头文件嵌套包含. 方法一: #ifndef __SOMEFILE_H__ #define __SOMEF ...

  3. C/C++ 防止头文件重复包含 #pragma once 与 #ifndef 的区别

    为了避免同一个头文件被多重包含/重复包含,有两种方式: 方式一: #ifndef XXX #define XXX ... ...  //声明语句 #endif  //XXX 方式二: #pragma ...

  4. 两个问题: 1、头文件重复包含 2、头文件加了ifndef条件预处理指令为什么还会定义

    第一个问题:编译时重定义 文件1.h void fun1(); struct A { int a char b; };   文件2.h #include"1.h" struct B ...

  5. cocos2d-x 扩充引擎基类功能 引起的头文件重复包含问题的分析

    c++ 头文件包含 原因的分析:   c++  头文件的循环引用是指: .h 里面的里面的头文件的相互包含的,引起的重复引用的问题.cpp 里面包含头文件是不存在重复引用的问题(因为CPP没有#ifn ...

  6. C++中头文件相互包含与前置声明

    一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...

  7. 自定义C/C++头文件以及头文件重复定义解决

    今天再看二叉树的知识,看着看着就看到C/C++的头文件及头文件重复定义这一块去了.以前就看到过这个问题,但是自己一直没有用到这方面的东西,今天遇到就顺便总结一下,等以后忘了再回来看看. 首先明确一点C ...

  8. 头文件的宏定义#ifndef测试

    一.入题 在头文件的书写中,都加入了如下内容: #ifndef __头文件名_H #define __头文件名_H #endif 曾经在书中看到的解释是“防止重复定义”,今天突然想到为什么是这样的解释 ...

  9. C/C++ 中头文件相互包含引发的问题

    转自:http://blog.csdn.net/hazir/article/details/38600419 今天下午遇到一个头文件相互包含而导致的编译问题,花了我不少时间去调试没找到问题,最后晚上跟 ...

随机推荐

  1. 1086. Tree Traversals Again (25)-树的遍历

    题意:用栈的push.pop操作给出一棵二叉树的中序遍历顺序,求这棵二叉树的后序遍历. 需要一个堆结构s,一个child变量(表示该节点是其父亲节点的左孩子还是右孩子),父亲节点fa对于push v操 ...

  2. BLE资料应用笔记 -- 持续更新(转载)

    简而言之,蓝牙无处不在,易于使用,低耗能和低使用成本.’让我们’更深入地探索这些方面吧. 蓝牙无处不在—,您可以在几乎每一台电话.笔记本电脑 .台式电脑和平板电脑中找到蓝牙.因此,您可以便利地连接键盘 ...

  3. Alpha阶段个人贡献分

    根据任务完成情况与之前的评分标准,我们给组员分数如下: 团队成员 最终得分 程刚 49 李睿琦 50 刘丽萍 52 刘宇帆 53 王力民 54 杨昊岚 41 左少辉 51 转会人员: 杨昊岚转到Our ...

  4. 2013337朱荟潼 Linux第十八章读书笔记——调试

    第十八章 调试 0.总结 oops 内核的调试配置 用Git进行二分搜索 bug总会有,简洁描述发给LKML 1. 准备开始 在用户级的程序里,bug表现比较直接:在内核中却不清晰. 2. 内核中的b ...

  5. Iterative Quantization,ITQ

    Abstract 针对大规模的图像检索问题,论文提出了一个高效的ITQ算法.该算法先将中心化后的数据映射到超立方体的顶点上,再通过优化过程寻找一个旋转矩阵,使得数据点经过旋转后,与超立方体的顶点数据具 ...

  6. ElasticSearch 2 (28) - 信息聚合系列之高层概念

    ElasticSearch 2 (28) - 信息聚合系列之高层概念 摘要 和查询表达式(query DSL)一样,聚合也有一种可编辑的语法:可以根据我们的需要混合以及匹配使用独立的功能单元.这也就是 ...

  7. C语言入门:04.数据类型、常量、变量

    一.数据 1.什么是数据 生活中时时刻刻都在跟数据打交道,比如体重数据.血压数据.股价数据等.在我们使用计算机的过程中,会接触到各种各样的数据,有文档数据.图片数据.视频数据,还有聊QQ时产生的文字数 ...

  8. Android控件第1类——TextView

    Android提供TextView,它不能被编辑,它的子类EditText可以编辑.TextView有很多子类. 1.EditText,继承自TextView EditText可以编辑. 可以设置in ...

  9. MySQL的order by时区分大小写

    Mysql 查询区分大小写 mysql查询默认是不区分大小写的 如: select * from some_table where str=‘abc'; select * from some_tabl ...

  10. DevExpress15.2+VS2015 破解、汉化

    破解 下载有效的激活工具DEV15.X在VS2015 (亲测),地址 http://download.csdn.net/download/u011149525/9581176 解压后的注册说明: 感谢 ...