#ifndef 标识符(常用:_XXX_H)
#define 标识符(常用:_XXX_H)
.....................
#endif
1.简介:
ifndef是"if not defined"的简写,是宏定义的一种,可以根据是否已经定义了一个变量来进行分支选择,
是预处理功能三种(宏定义,文件包含和条件编译)中的第三种----条件编译。
(之所以采用条件编译而不采用条件语句进行分支选择,是因为前者相较于后者生成的目标代码程序更短)
2.功能:防止头文件被重复包含和编译。
(注意:防止源文件两次包含同一个头文件,而不是防止头文件被两个不同的源文件包含)
3.缺失风险:
①重复定义
②无限循环编译
4.原理:
①判断是否宏定义过:_XXX_H
②如果没有宏定义过,那么宏定义:_XXX_H
③顺序编译#ifndef _XXX_H 至 #endif之间的语句
④当一个源文件重复调用同一个头文件(调用编译头文件的实质就是将头文件所包含的代码拷贝一份到调用语句处),
④由于之前有调用编译历史(宏定义过),所以#ifndef _XXX_H 至 #endif之间的语句不会被重复调用
例:
//file: test.cpp(test.cpp里包含了a.h和b.h) //file: a.h(a.h里包含了b.h)
#include <a.h> #include <b.h>
#include <b.h> ······
······
由上可知,此时b.h就会被包含和编译两次。
①如果b.h中定义了一个变量b,在编译test.cpp时就会报重复定义的错误。(重复定义)
②如果b.h里包含了a.h,那么a.h,b.h就会循环包含,预处理阶段就会不停地循环展开头文件。(无限循环编译)
解决办法:(以无限循环为例)
//file: test.cpp //file: a.h(a.h里包含了b.h) //file: b.h(b.h里包含了a.h)
#include <a.h> #ifndef _A_H #include <a.h>
#include <b.h> #define _A_H ······
······ ······
#include <b.h>
······
#endif
······
解释:
在预处理阶段,会先展开test.cpp中的头文件a.h,执行到#ifndef _A_H_,发现此时_A_H_并没有被define,所以继续执行#define _A_H_(此时_A_H_就被define了)直到#endif;当展开b.h,执行到文件里的#include <a.h>,进入a.h执行#ifndef _A_H_时,发现_A_H_已经被define了,所以直接跳到a.h里endif之后的语句执行。这样子就可以保证a.h不会被重复包含。如果要确保b.h不会被重复包含就该写成:
//file: b.h(b.h里包含了a.h)
#ifndef _B_H
#define _B_H
······
#include <a.h>
······
#endif
······
5.总结:所有的头文件前后都加上:
#ifndef 标识符(常用:_XXX_H)
#define 标识符(常用:_XXX_H)
.....................
#endif