6.7 习题
1.什么是预编译,何时需要预编译?
【解答】预编译就是指程序执行前的一些预处理工作,主要指用#来表示的一系列表达式。使用预编译主要针对:
●总是使用不经常改动的大型代码体。
●程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。
2.编写一个标准宏MIN,这个宏输入两个参数并返回较小的一个,注意参数在调用时可能是表达式的情况。
【解答】该习题主要考查宏定义的定义和使用。宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括号中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。读者需要谨慎地将宏定义中的“参数”和整个宏用括号括起来,所以严格地讲下述解答都是错误的:
正确的写法应如下所示:
3.编写一个C++程序,在程序中定义一个不带参数的宏PI,使其完成求给定半径的圆的周长和面积。
【解答】该习题主要考查宏在具体程序中的应用。根据前面章节的学习,读者知道求给定圆半径的周长和面积可以通过声明变量和常量来实现,其中由于PI是不会变的,其值为3.14,因此可以将其声明为常量。在学习了宏后,可以将该常量声明为宏,其他语句不变。其简要实现代码如下所示。
4.下面程序段定义了两个宏,在主函数main()中使用了条件编译语句来控制程序的运行,读者仔细理解并写出输出结果。
【解答】上述代码中,定义了带参数的CIR(r),其在主函数main()中展开后为z=x+y*x+y,将x和y的值代入,因此z=5。而条件编译语句#ifdef TEST表示,如果TEST已被定义则执行下边的语句,因此程序将输出x、y和z的值,输出结果如图6-18所示。
图6-18 编译预处理
5.宏可以带参数,而且带参数的宏与带参数的函数的写法和调用都很相似,但是其存在本质上的不同,其区别在何处,请试着通过两个例子进行说明。
【解答】该习题主要考查函数和宏的区别。函数调用时要把实参表达式的值求出来再赋予形参,而宏代换中对实参表达式不进行计算,直接地代换。这导致了即使把同一表达式用函数处理与用宏处理,两者的结果也有可能是不同的。下面通过具体例子进行说明。如下分别定义了一个带参宏和带参函数,其函数名为SQ,形参为Y,函数体表达式为((y)*(y)),而宏定义也定义字符串为((y)*(y))。
从输出结果来看,使用函数和使用带参数的宏得到的结果却大不相同。这是因为在函数定义代码中,函数调用是把实参i值传给形参y后自增1,然后输出函数值,因而要循环5次。输出1~5的平方值。而在宏定义代码中宏调用时,只做代换。SQ(i++)被代换为((i++)*(i++))。每次循环后i的值会增加2,因此只做3次循环。