两道面试题隐藏的陷阱

最近因为要换工作,所以也不时去搜索一些面试题看一下。下面两道题都是很常见的题,但却隐藏了一些陷阱。

1. 不使用中间变量,交换两个int型的值

    这道题网上很常见,通常可能会给出下面这种答案:

    a ^= b ^= a ^= b;

    运行一下,结果可能是正确的。

    哦!为什么是可能呢?

    这里,我们应该首先介绍一个概念:序列点(sequence point)。ANSI C告诉我们:序列点是一个时间点(在整个表达式全部计算完毕之后或在 ||、  &&、 ? : 或逗号 运算符处, 或在函数调用之前), 此刻尘埃落定, 所有的副作用都已确保结束。并且,更加重要的是:在上一个和下一个序列点之间, 一个对象所保存的值至多只能被表达式的计算修改一次。

    在这里,a被修改了两次,所以它是无定义的。

    那么,我们可以修改一下:

    a ^= b;

    b ^= a;

    a ^= b;

    此时,序列点的问题就消除了,但是,还是有问题。

    当a 与 b相同时,计算完成后,a = b = 0!这可不是我们想要的。

    所以我们必须要加上额外的判断语句,完整的程序可能是下面这样的:

   void exchange(int *a,int *b)

   {

        if(*a == *b)

             return;

        *a ^= *b;

         *b ^= *a;

        *a ^= *b;

    }

    看上去,它要比使用中间变量的版本更加复杂,并且,没有证据表明这个版本有什么性能上的优势。

2. 不使用if,switch等条件判断语句,比较两个int型值的大小。

    这个也比较常见,有这样一种可能的答案:

    int max = (a + b + abs(a - b)) / 2;

    看上去很巧妙,是的,但它忽略了一个问题:a+b 与a -b 都可能产生溢出,从而得出完全错误的结果。

    事实上,使用>,<这些比较符是最聪明的做法,当然,这里我们需要使用其他方法来得出一个结果。

    一种可能的方法是:

    long long int max = ((long long)a + b + llabs((long long)a - b))/2;

    /* long long is support by C99 */

    通过使用更长的类型,可以保证得到正确的结果,但显然很麻烦:)

   

    这两个问题都很简单,但是给出的答案都有一些缺陷,我们也可以总结出几条教训。

    1. 一行代码只完成一件事。

    2. 使用巧妙的代码要谨慎,简单清楚地代码更可靠。

 

参考:

    MSDN C Reference

    C FAQ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值