16道c语言面试例子【2】:

2.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(x,y) ((x)<=(y)?(x):(y))
这个测试是为下面的目的而设置的:
1):标识#define在宏中应用的基本知识。这是很重要的,因为在没有嵌入(inline)操作符变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的办法。
2):三重条件操作符的知识。这个操作符存在c语言中的原因是它使编译器能产生比if then else更优化的代码,了解这个用法很重要。
3):懂得在宏中小心地把参数用括号括起来。
4):我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++,b);
【关于least = MIN(*p++,b);这个问题原作者并没有回答。我想这里可能是考虑到++优先于*,这样的话传进来的就是一个野指针了。可作者说的是考宏的副作用。于是我google了一下,在这个博客找到了不错的答案:http://www.cnblogs.com/haimingwey/archive/2012/05/25/2518219.html】
原文如下:


一道思考题:

写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你运行”least = MIN(*p++, b); “代码时会发生什么事?

解答: #define MIN(A,B)  ( (A) <= (B) ?  (A) : (B) )     MIN(*p++, b)会产生宏的副作用。
剖析: 这道题考察对宏定义的使用,宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。             程序员对宏定义的使用要非常小心,特别要注意两个问题:
(1)谨慎地将宏定义中的“参数”和整个宏用用括弧括起来。所以,严格地讲,下
          述解答: #define MIN(A,B) (A) <= (B) ? (A) : (B)       #define MIN(A,B) (A <= B ? A : B )  都是错误的。
(2)防止宏的副作用。宏定义#define MIN(A,B) ((A) <= (B) ? (A) : (B))对MIN(*p++, b)的作用结果是: ((*p++) <= (b) ? (*p++) : (b)) 这个表达式会产生副作用,指针p会作二次++自增操作。
          除此之外,另一个典型的错误解答是: #define MIN(A,B) ((A) <= (B) ? (A) : (B)); 这个解答在宏定义的后面加“;”,显示编写者对宏的概念模糊不清。