码迷,mamicode.com
首页 > 编程语言 > 详细

C++的一道笔试题

时间:2015-08-26 20:13:59      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:c++   c语言   

void swap_int(int *a,int *b){
  *a=*a+*b;
  *b=*a-*b;
  *a=*a-*b;
}

以下说法正确的是:
  • 结果不正确,因为会溢出,用位与的方式就没问题
  • 结果正确,即使会溢出
  • 结果正确,不会溢出

  • 其他选项都不对
设整形变量*a、*b的位表示为
*a = n31n30 ··· n0
*b = m31m30 ··· m0
只有当*a > 0 && *b > 0 或 *a < 0 && *b < 0时才会发生溢出。两者类似,只证明均大于0时的情况。
必须扩展额外一位才能够容纳正确的结果,‘|‘左边为扩展位。
*a = 0|0n30 ··· n= n30*230 +  n29*229 + ··· + n0*20 = N
*b = 0|0m30 ··· m0 = m30*230 +  m29*229 + ··· + m0*20 = M
若和溢出,则33位表示必为
*a + *b = 0|1b30 ··· b= -231 + b30*230 +  b29*229 + ··· + b0*2=  2 31  + B  
计算机将得到的33位结果truncate回原来的32位,即丢弃第33位(0)变为:
*a + *b =    1b30 ··· b= -231 + b30*230 +  b29*229 + ··· + b0*20 = -2  31   + B ②
正确的真实值是①,溢出结果为②,可见溢出结果=真实值-2 32 
则*b = *a - *b = ② - *b =  ① - 232 - *b = *a + *b - 232 - *b = -232 + *a
最后一步,来看 -232 + *a  == *a 成立否?
0 < *a < 231, 则 -232 < -232 + *a < -231,和仍需要扩展1位方能表示:
*a    = 0|0n30 ··· n= n30*230 +  n29*229 + ··· + n0*20 = N
-232 = 1|0000 ··· 00
 和的位表示为
-232 + *a = 1|0n30 ··· n= n30*230 +  n29*229 + ··· + n0*20
同样,计算机把33位结果truncate回32位(丢弃第33位)得到:
-232 + *a =  0n30 ··· n= n30*230 +  n29*229 + ··· + n0*20 = *a
可见-232 + *a  == *a 是成立的。因此尽管溢出了,但仍能正确交换。

按照我们的惯性思维,加减法会造成溢出,但是先加后减之后原来溢出的又溢回来了,所以运行结果是正确的。
以后笔/面试过程中还要注意运算溢出等问题。还有switch中是否有break,或运算的短路,fork后的代码是要被
重复执行的等等问题,这些问题平时编程当然都会注意,但是出成题目还是很有迷惑性的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

C++的一道笔试题

标签:c++   c语言   

原文地址:http://blog.csdn.net/yuanliang01xiaolang/article/details/48008229

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!