条件编译是指预处理器根据条件编译指令,有条件地选择源程序代码中的一部分代码作为输出,送给编译器进行编译。主要是为了有选择性地执行相应操作,防止宏替换内容(如文件等)的重复包含。
常见的条件编译指令如下:
条件编译指令 | 描述(Description) |
---|---|
#if | 如果条件为真,则执行相应操作 |
#elif | 如果前面条件为假,而该条件为真,则执行相应操作 |
#else | 如果前面条件均为假,则执行相应操作 |
#endif | 结束相应的条件编译指令 |
#ifdef | 如果该宏已定义,则执行相应操作 |
#ifndef | 如果该宏没有定义,则执行相应操作 |
#define | 定义一个宏 |
#undef | 取消一个宏定义 |
严格来说,#define与undef不能算是真正的条件编译,虽然他也是在编译阶段完成,下面介绍几组常见的条件编译组合。
#if 条件表达式
程序段1
#else
程序段2
#endif
#include
using namespace std;
int main()
{
int a,b,c;
a = 10;
b = 20;
c = 30;
#if 1
printf("a+b = %d",a+b);
#else
printf("b+c = %d",b+c);
#endif
system("pause");
return 0;
}
上述这段简单的程序,当#if旁边为TRUE,为真时,执行#if 下面的语句块直到#else之上的所有。
当#if旁边为FALSE,为假时,执行#else下面的语句块,直到#endif之上的所有。
#ifndef 标识符
#define 标识符 替换列表
//...
#endif
#include
using namespace std;
#ifndef MAX //检查是否已定义
#define MAX 1024 //没有定义就使用该行
#endif //结束标识
int main()
{
system("pause");
return 0;
}
该条件编译指令更重要的一个应用是防止头文件重复包含。
如果 f.cpp 源文件中包含 f1.h 和 f2.h 两个头文件,而 f1.h 头文件及 f2.h 头文件中均包含 x.h 头文件,则 f.cpp 源文件中重复包含 x.h 头文件。可采用条件编译指令,来避免头文件的重复包含问题。所有头文件中都按如下格式:
#ifndef _HEADNAME_H_
#define _HEADNAME_H_
//头文件内容
#endif
Code解释:当该头文件第一次被包含时,由于没检测到该头文件名对应的符号(宏名)HEADNAME_H,则定义该头文件名对应的符号(宏),其值为该系统默认。并且,该条件编译指令选中 #endif 之前的头文件内容;如果该头文件再次被包含时,由于检测到已存在以该头文件名对应的符号(宏名),则忽略该条件编译指令之间的所有代码,从而避免了重复包含。
该条件编译即是第一种的升级版——puls版本
#if 条件表达式1
程序段 1
#elif 条件表达式2
程序段 2
#else
程序段3
#endif
功能:先判断条件1的值,如果为真,则程序段 1 被选中编译;如果为假,而条件表达式 2 的值为真,则程序段 2 被选中编译;其他情况,程序段 3 被选中编译。
示例:
#include
using namespace std;
int main()
{
int a,b,c;
a = 10;
b = 20;
c = 30;
#if 0
printf("a+b = %d",a+b);
#elif 1
printf("a+c = %d",a+c);
#else
printf("b+c = %d",b+c);
#endif
system("pause");
return 0;
}
上述程序就是第一个的升级版,想必,不难理解,就是判断两次,第一次为1,就不往下走,第一次若是为0,则判断第二次,同上规则。
#ifdef 标识符
程序段
#endif
功能:如果检测到已定义该标识符,则选择执行相应程序段被选中编译;否则,该程序段会被忽略。
示例:
#ifdef N
#undef N
//程序段
#endif
Code解释:如果检测到符号 N 已定义,则删除其定义,并选中相应的程序段。
定义宏分为两种:
第一种:对象宏(宏常量定义)
第二种:函数宏
// 常量定义
#define MAX_LENGTH 100
// 通用标识,日志输出宏
#define SLog printf
// 预编译宏
#define _DEBUG
// 最小值函数
#define MIN(a,b) ((a)>(b)? (a):(b))
// 安全释放内存函数
#define SAFE_DELETE(p) {if(NULL!=p){delete p; p = NULL;}}
关于undef上面的例子中已经有了,只是没有说明,单一功能,删除当前宏。
这里就不多说,上面例子中有示例。
当然宏的底层还可以讲的有很多,比如汇编剖析宏。由于本人的知识水平有限,暂时只能局限于上层使用了。如果有机会,有实力浅谈汇编的时候,再进一步聊聊宏的汇编。
版权声明:转载请注明出处,谢谢!