网易笔试题-- 宏定义的那点事

     过了很久,现在突然想起了一道网易TTT计划中的一道笔试题,是关于宏定义的,但是对于宏定义很不了解,现在记录一下,大概整理一下思路,不知道对不对,希望大家勿喷。

    具体的题目记不大清楚了,大概是根据以下两种宏定义的表达,问在程序编译和运行时,可能会出现什么不同的结果。

  第一种宏定义表达:

#define max( a, b )  ( a > b ) ? a : b

  第二种宏定义的表达:

#define max( a, b )  ({ int A = a ; int B = b ;( A > B ) ? A : B;})

  

  笔试结束之后,我大概的查阅了一些资料,大概知道了一下。以下的内容有的是借鉴别人的分析,

一:第一种形式的分析

 对于第一种表达,表面上看上去不会有什么不妥,但是在实际的程序调用中就会出现bug,看下面的例子(例1):

int a = 3;
int b = 4;
int c = 2 * max( a++, b++);
//本来程序想要的结果是 c = 2 * 5;即c = 10;
//但是实际的结果是: c = 12;

 为什么呢?

根据宏定义的执行过程,我们知道,在程序编译时,编译器自动将使用了宏定义的地方进行展开,对于普通的宏定义即例如(例2):

#define PI 3.1415926

  程序编译过程中只是简单的查找和替换,所以,将使用了PI的地方全部替换成3.1415926是不会出现意想不到的错误的。虽然例2的编译过程也是替换,下面来看一下,具体的替换过程:

int c = 2 * max( a++, b++);
//=> c = 2 * (a++ > b++ ? a++ :b++ )

想必大家看到这里就应该明白了,为什么结果是12而不是10了吧,原因很简单,宏定义进行替换的时候,是将所有的参数一起替换,不是将参数的运算的结果计算出来之后再做相应的替换的。

对于上面的错误,在编译器的第三版本可以使用

#define max(a,b) ( (a) > (b) ? (a) : (b) )

来规避错误,但是当程序中使用下面的例子的时候,意想不到的事情又会不期而至

int c = 2 * max (3 , 4 > 5 ? 4 : 5)

以下进行展开:

int c = 2 * (max(3,4 > 5 ? 4 : 5));
   //=> c = 2 * (3 > 4 > 5 ? 4 : 5 ? 3 :4 > 5 ? 4 : 5)
   //=> c = 2 * ((3 > (4 > 5 ? 4 : 5 )? 3 :4) > 5 ? 4 : 5)
   //=> c = 2 * ((3 > 5 ? 3 : 4) > 5 ? 5 : 4)
   //=> c = 2 * (4 > 5 ? 5 :4)
   //=> c = 2 * 4 
   //=> c = 8

这种情况又怎样解决呢?

第二种的分析,请看下一篇博文:宏定义续


转载于:https://my.oschina.net/u/1767433/blog/261793

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值