首页 > 其他 > 详细

编写安全的代码——小心有符号数的右移操作

时间:2014-03-13 02:33:21      阅读:489      评论:0      收藏:0      [点我收藏+]

  在嵌入式开发当中,做数据运算(乘、除)等表达式时,移位操作是工程师们的最爱。但是也要非常谨慎,比如有符号数和无符号数、变量的取值范围
来看看这样一段小代码

#include <stdlib.h>

#include <stdio.h>

static void divide_by_two(int num)

{

  while (num){

  printf("%d\n", num);

  num /= 2;

  }

}

int main(void)

{

  int num;

   scanf("%d", &num);

   divide_by_two(num);

   return 0;

}

这是一个朋友写的程序,他呢,看觉得num /= 2,想起课程上讲过,整数右移一位,就等于除于二,并且右移操作比除法运算要高效的多。于是将 num /=2 改为了 num = num>>1。
于是代码变为
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. static void divide_by_two(int num)
  4. {
  5.     while (num){
  6.         printf("%d\n", num);
  7.         num = num>>1;
  8.     }
  9. }
  10. int main(void)
  11. {
  12.     int num;
  13.     scanf("%d", &num);
  14.     divide_by_two(num);
  15.     return 0;
  16. }  
  17. 输入正数测试时,没问题,ok !  
    1. 当输入负数时说他的程序陷入了死循环:
  1. [cheng@localhost test]$ ./a.out
  2. -5
  3. -5
  4. -2
  5. -1
  6. -1
  7. -1
  8. 。。。。。。
  9. -1
那么到底是什么原因呢?我当时也没找出问题的根源,可是回来仔细推敲一番,我以十六进制的方式打印了下结果,果然。生无符号数与有符号数在作怪!右移一位就等于除以2,但是这里需要加一个条件,这里指的是正数。而对于有符号整数,且其值为负数时,在C99标准中对于其右移操作的结果的规定是implementation-defined.运行到最后,对于 -1(十六进制0xffffffff)(二进制1111 1111  1111 1111 1111 1111 1111 1111)不管你怎么移位,一直都是这个数,问题就是这!所以进入了死循环。

要注意的是:为了明确传入的参数,你最好加入特定类型  。比如你要传入的是有符号的整形。你就这样定义:signed int 等价于 int.要是你想传入的是无符号的整形数呢,你就定义成:unsigned int  。通过这样明确限定,就算是误传的话,编译器也会强制转换

编写安全的代码——小心有符号数的右移操作,布布扣,bubuko.com

编写安全的代码——小心有符号数的右移操作

原文:http://www.cnblogs.com/chengliangsheng/p/3596954.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!