防止头文件重复包含之pragma once与#ifndef

在我们自己编写 C/C++的头文件时,可能会忽略一点:用一些处理机制来避免头文件的重复包含,因为头文件的内容在预编译时是把头文件的内容完全拷贝到引入的地方替换头文件的包含命令,而包含的头文件可能有包含很多内容,所以要是重复包含头文件,可能会使预编译后的源文件代码冗余量很大,造成空间上的浪费。
目前自己用过两个防止头文件重复包含的方法:
1、 #pragma once
2、 #ifndef
  #define
  #endif
  
它们具体实现如下:
假定此时要保证头文件HeadFile.h不会被重复包含,那么两种方法对应的方式如下:
1、 #pragma once
  直接把它放在HeadFile.h文件实现的最前面,即可实现。
  

  #pragma once//头文件的具体实现

2、 #ifndef
  #define
  #endif

  #ifndef __HEADFILE.H__#define __HEADFILE.H__//头文件的具体实现#endif

两种方法的一些差异:
1、 #pragma once由编译器提供保证:同一个文件不会被编译多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
2、 #ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况。

#pragma once是编译器相关的,有的编译器支持,有的编译器不支持,具体情况请查看编译器API文档,不过现在大部分编译器都有这个杂注了。
#ifndef,#define,#endif是C/C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。

方式一可以避免名字冲突,方式二由语言支持所以移植性好
#pragma once方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受语言天生的支持,不受编译器的任何限制;而#pragma once方式却不受一些较老版本的编译器支持,换言之,它的兼容性不够好。也许,再过几年等旧的编译器死绝了,这就不是什么问题了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526171.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识C++之继承

1、何为继承 C中所谓继承,就是在一个已存在类的基础上创建一个新的类,新类获得已存在类的部分特性(为什么是部分特性,后面会讲到)。已存在类被称为基类(Base Class)或父类(Father Cl…

初识C++之函数重载、重写、重定义的区别

在C的学习中,慢慢接触了一些很容易混淆的名词,今天就来剖析几个容易混淆的名词。 1、函数重载   重载函数是函数的一种特殊情况,为方便使用,C允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参…

初识C++之封装

学习C不得不说到C的三大特性:封装、继承、多态,今天就先来剖析一下他的封装性。 1、什么是封装   封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进…

初识C++之虚函数

1、什么是虚函数   在基类中用virtual关键字修饰,并在一个或多个派生类中被重新定义的成员函数,用法格式为:   virtual 函数返回类型 函数名(参数表)    {     函数体    }    虚函数是实现多态性…

初识C++之多态

多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。 1、什么是多态   多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的…

从尾到头打印单链表(C语言)

void PrintListTailToHead(PSListNode pHead) {if (NULL ! pHead){//递归实现PrintListTailToHead(pHead->pNextNode);printf("%d ", pHead->data);} } 递归方式很容易就能实现。

删除一个无头单链表的非尾节点(C语言)

void DelNotTailNode(PSListNode pos) {PSListNode pNode NULL;assert(pos);if (NULL pos->pNextNode){return;}else{DataType temp 0;//交换pos和pos->pNextNode的数据(相当于交换了两个结点的位置),使问题转换为删除pos指向的结点…

在无头单链表的一个非头节点前插入一个节点(C语言)

①时间复杂度为N: void InsertNotHead(PSListNode pHead, PSListNode pos, DataType data) {PSListNode pPreNode pHead;PSListNode pPreNode pHead;if (NULL pos){return;}else{//先找到pos结点前面的结点while(pCurNode ! pos){pPreNode pCurNode;pCurNode …

单链表实现约瑟夫环(JosephCircle)(C语言)

//使链表形成一个环 void FormCyc(PSListNode *pHead) {if (NULL pHead){return;}else{PSListNode pNode *pHead;while (NULL ! (pNode->pNextNode)){pNode pNode->pNextNode;}pNode->pNextNode *pHead;} }PSListNode JosephCircle(PSListNode pHead, int M) {if …

逆置/反转单链表(C语言)

1、逆置链表:前插法 void ReverseList(PSListNode* pHead) {if (NULL *pHead){return;}else{//创建一个新的空链表,遍历pHead指向的链表里的所有节点,每找到一个,就前插到新链表里PSListNode pNewHead *pHead;*pHead (*pHead)…

单链表排序(冒泡排序)(C语言)

优化版: void SortList(PSListNode pHead) {if (NULL pHead){return;}else{int flag 0;PSListNode pTailNode NULL;//当设置的尾节点与头结点指向同一个节点时,说明只有一个元素为排序,那么冒泡完成while (pTailNode ! pHead){PSListNode…

合并两个有序链表,合并后依然有序(C语言)

PSListNode MergeList(PSListNode pL1, PSListNode pL2) {PSListNode pNewNode NULL;PSListNode pListNode1 pL1;PSListNode pListNode2 pL2;PSListNode pNode NULL;if (NULL pListNode1){return pListNode2;}else if (NULL pListNode2){return pListNode1;}else{//先把新…

查找单链表的中间节点,要求只能遍历一次链表(C语言)

PSListNode FindMidNode(PSListNode pHead) {if (NULL pHead){return NULL;}else{//快慢指针,快指针一次循环走两步,慢指针一次循环走一步PSListNode pSlow pHead;PSListNode pFast pHead;//注意结束条件得加上NULL ! pFast->pNextNode&#xff0c…

查找单链表的倒数第k个节点,要求只能遍历一次链表(C语言)

PSListNode FindLastKNode(PSListNode pHead, int K) {if ((NULL pHead) || (K < 0)){return NULL;}else{PSListNode pFast pHead;PSListNode pSlow pHead;//利用快慢指针&#xff0c;让快指针先走K-1步&#xff0c;然后两指针同时走&#xff0c;直到快指针指向的下一个结…

判断单链表是否带环?若带环,求环的长度?求环的入口点?(C语言)

PSListNode HasCycle(PSListNode pHead) {if ((NULL pHead) || (NULL pHead->pNextNode)){return NULL;}else{PSListNode pFast pHead->pNextNode->pNextNode;PSListNode pSlow pHead->pNextNode;//利用快慢指针&#xff0c;让快指针每次走两步&#xff0c;慢指…

判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】(C语言)

int IsListCroseWithCycle(PSListNode pL1, PSListNode pL2) {PSListNode pMeetNode1 HasCycle(pL1);PSListNode pMeetNode2 HasCycle(pL2);if ((NULL pL1) || (NULL pL2)){return 0;}//两个链表都没环的情况else if ((NULL pMeetNode1) && (NULLpMeetNode2)){PSL…

求链表相交时的交点(C语言)

//链表相交时的交点 PSListNode IntersectionNode(PSListNode pL1, PSListNode pL2) {int count1 0;int count2 0;PSListNode PSList1 pL1;PSListNode PSList2 pL2;PSListNode pMeetNode1 HasCycle(pL1);PSListNode pMeetNode2 HasCycle(pL2);if ((NULL pL1) || (NULL …

求两个已排序单链表中相同的数据(C语言)

PSListNode ByeNode(DataType data) {PSListNode pNewNode (PSListNode)malloc(sizeof(struct SListNode));if (NULL ! pNewNode){pNewNode->data data;//注意使开辟的新节点的指向为空pNewNode->pNextNode NULL;}return pNewNode; }PSListNode UnionSet(PSListNode p…

浅析Linux开发工具之gcc/g++

在windows开发平台&#xff0c;我们用惯了vc、vs等IDE&#xff08;集成开发环境&#xff09;&#xff0c;在编译好源代码之后&#xff0c;按下相应按钮&#xff0c;IDE就会为我们完成编译&#xff0c;链接的过程。然而在Linux平台下&#xff0c;却没有这么方便的开发环境&#…

Linux权限的简单剖析

一、权限是什么 权限&#xff08;privilege&#xff09;是指某个特定的用户具有特定的系统资源使用权力。举个简单的例子&#xff0c;夏日炎炎&#xff0c;你看到路边有卖西瓜的&#xff0c;你想要吃西瓜&#xff0c;你就得买它&#xff0c;买它其实就是获取你对西瓜的使用权限…