![21天学通C++(第5版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/312/31186312/b_31186312.jpg)
6.4 条件编译
预处理程序除了提供上面介绍的宏定义和文件包含功能,还提供了条件编译的功能。条件编译可以按不同的条件编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。C++中的条件编译有三种形式,下面分别介绍。
6.4.1 #ifdef形式
#ifdef形式是指该形式的第一个编译命令为#ifdef,这种形式的结构如下所示:
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_51.jpg?sign=1739368257-0qgXcEqvSRszV4qKqVsLJteip3JW5Aab-0-e7e58e23e9a7f639169fd57e35902194)
该形式的条件编译功能是,如果标识符已被#define命令定义过,对程序段1进行编译,否则对程序段2进行编译。如果没有程序段2(其为空),则本形式中的#else可以没有,即其形式可以改写为如下:
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_52.jpg?sign=1739368257-926q0BCVvoWxagrJzibxAKL00AjEJJAX-0-735847800758dea0fc17c8dd7723c935)
【范例6-13】#ifdef预编译命令的应用。该范例根据是否定义了PI来编译不同的程序块,如果定义了则编译计算圆面积的程序块,否则编译计算正方形面积的程序块,实现代码如代码清单6-13所示。
代码清单6-13
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_53.jpg?sign=1739368257-eTdByw57R8IPlbsGpnbpmV0kdfATsfVC-0-e17e63ea155c0e1e1d20afef8e2481b3)
【运行结果】由于在程序的第6行插入了条件编译预处理命令,因此系统将根据PI是否被定义过来决定编译哪一个程序块的语句。而在程序的第1行已对PI做过宏定义,因此应对第一个程序块的语句做编译,因此运行结果如图6-15所示。
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_54.jpg?sign=1739368257-uoYDGK6xtpr7HbepC2GNglngSJSNDpfB-0-fe3a741574a60b880c3c2acd1a2f88e9)
图6-15 计算圆面积
在上述程序中,如果将第1行语句注释掉,那么系统将编译第二个程序块语句,即计算正方形的面积,而不是圆面积,运行结果如图6-16所示。
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_55.jpg?sign=1739368257-sVhVDEU8sRIRa9nsUPs36sdmNcw5hG46-0-5fcdc4e41271fcea9d57246c56a64171)
图6-16 计算正方形面积
注意
在编译上述程序段时,不管是否将第1行代码注释,系统都会给出两个警告信息,这是正常现象。如果读者想消除这个警告,可以将定义变量的语句放在各个程序块中。
【范例解析】在上述代码中,当定义了变量PI时,第二个程序段将不会被编译,因此变量a和ss没有被用到,系统将给出警告信息;而当注释第1行代码,也即没有定义PI,则第一个程序段不会被编译,因此变量radius和sr将不会被用到,系统也将给出警告信息。一般来说,此处可以忽略该警告信息,直接运行程序即可。
6.4.2 #ifndef形式
#ifndef形式是指该形式的第一个编译命令为#ifndef,这种形式的结构如下所示:
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_56.jpg?sign=1739368257-X9gkeF7hKMX03bXsBQVh5qB5qkDMrJ2a-0-caa61e86bfdb0a027ec3d25100a5be58)
#ifndef形式与第一种形式的区别是将“ifdef”改为“ifndef”。其功能是,如果标识符未被#define命令定义过,则对程序段1进行编译,否则对程序段2进行编译。读者可以看出,#ifndef形式与第一种形式的功能正相反。
提示
关于这种形式的条件编译语句在具体程序中的应用,读者可以直接修改上述代码清单6-14,看是否达到预期的目的,此处就不再赘述了。
6.4.3 #if形式
#if形式是指该形式的第一个编译命令为#if,结构如下所示:
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_57.jpg?sign=1739368257-8YiBe76MXZ7QhNxGTpYDkgIRfuBUJ4aW-0-f104b2458f67b47b898dd15c6bde0950)
这种形式的条件编译结构功能是,如常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此其可以使程序在不同条件下,完成不同的功能。
【范例6-14】#if预编译命令的应用。该范例将范例6-13进行修改,使其利用#if形式达到同样的功能,其实现代码如代码清单6-14所示。
代码清单6-14
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_58.jpg?sign=1739368257-EAZY9aniQXgRb8Lqh8tGbSTqn6SrH4P3-0-bedf3cf49bdbc5c8e96f7c83af5799b4)
【运行结果】将上述代码在Visual C++中执行,其结果如图6-17所示。
![](https://epubservercos.yuewen.com/E623DA/16896237004359006/epubprivate/OEBPS/Images/txt008_60.jpg?sign=1739368257-fIGOIU4kVUp1aAOOf9yn1Vy8kRmE4mBZ-0-1e799afe6b9da0ecfc71fe5a09139fa9)
图6-17 条件编译
【范例解析】读者看到,上述代码只是修改了第1行代码,定义一个无关的常量,在后续的代码中用#if来判断该常量是否非0,是则执行程序块1,否则执行程序块2。在上述代码中定义的常量flag为1,执行计算圆面积的程序块。
当然,上面介绍的条件编译也可以用条件语句来实现。但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短。
提示
一般来说,在实际程序中,如果条件选择包含的程序段很长,采用条件编译的方法是十分必要的。