6.4 条件编译
预处理程序除了提供上面介绍的宏定义和文件包含功能,还提供了条件编译的功能。条件编译可以按不同的条件编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。C++中的条件编译有三种形式,下面分别介绍。
6.4.1 #ifdef形式
#ifdef形式是指该形式的第一个编译命令为#ifdef,这种形式的结构如下所示:
该形式的条件编译功能是,如果标识符已被#define命令定义过,对程序段1进行编译,否则对程序段2进行编译。如果没有程序段2(其为空),则本形式中的#else可以没有,即其形式可以改写为如下:
【范例6-13】#ifdef预编译命令的应用。该范例根据是否定义了PI来编译不同的程序块,如果定义了则编译计算圆面积的程序块,否则编译计算正方形面积的程序块,实现代码如代码清单6-13所示。
代码清单6-13
【运行结果】由于在程序的第6行插入了条件编译预处理命令,因此系统将根据PI是否被定义过来决定编译哪一个程序块的语句。而在程序的第1行已对PI做过宏定义,因此应对第一个程序块的语句做编译,因此运行结果如图6-15所示。
图6-15 计算圆面积
在上述程序中,如果将第1行语句注释掉,那么系统将编译第二个程序块语句,即计算正方形的面积,而不是圆面积,运行结果如图6-16所示。
图6-16 计算正方形面积
注意
在编译上述程序段时,不管是否将第1行代码注释,系统都会给出两个警告信息,这是正常现象。如果读者想消除这个警告,可以将定义变量的语句放在各个程序块中。
【范例解析】在上述代码中,当定义了变量PI时,第二个程序段将不会被编译,因此变量a和ss没有被用到,系统将给出警告信息;而当注释第1行代码,也即没有定义PI,则第一个程序段不会被编译,因此变量radius和sr将不会被用到,系统也将给出警告信息。一般来说,此处可以忽略该警告信息,直接运行程序即可。
6.4.2 #ifndef形式
#ifndef形式是指该形式的第一个编译命令为#ifndef,这种形式的结构如下所示:
#ifndef形式与第一种形式的区别是将“ifdef”改为“ifndef”。其功能是,如果标识符未被#define命令定义过,则对程序段1进行编译,否则对程序段2进行编译。读者可以看出,#ifndef形式与第一种形式的功能正相反。
提示
关于这种形式的条件编译语句在具体程序中的应用,读者可以直接修改上述代码清单6-14,看是否达到预期的目的,此处就不再赘述了。
6.4.3 #if形式
#if形式是指该形式的第一个编译命令为#if,结构如下所示:
这种形式的条件编译结构功能是,如常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此其可以使程序在不同条件下,完成不同的功能。
【范例6-14】#if预编译命令的应用。该范例将范例6-13进行修改,使其利用#if形式达到同样的功能,其实现代码如代码清单6-14所示。
代码清单6-14
【运行结果】将上述代码在Visual C++中执行,其结果如图6-17所示。
图6-17 条件编译
【范例解析】读者看到,上述代码只是修改了第1行代码,定义一个无关的常量,在后续的代码中用#if来判断该常量是否非0,是则执行程序块1,否则执行程序块2。在上述代码中定义的常量flag为1,执行计算圆面积的程序块。
当然,上面介绍的条件编译也可以用条件语句来实现。但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短。
提示
一般来说,在实际程序中,如果条件选择包含的程序段很长,采用条件编译的方法是十分必要的。