您的位置:首页 > 编程语言

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

2012-01-15 00:58 225 查看
编写安全代码——小心有符号数的右移操作 (2011-11-15 22:06)
标签: 有符号数 右移 安全代码 分类:

编写安全无错代码
作者:gfree.wind@gmail.com

博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net

话说有这样的一段代码:

#include <stdlib.h>

#include <stdio.h>

static void divide_by_two(int num)

{

while (num)
{

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

num /= 2;

}

}

int main()

{

int num;

scanf("%d",
&num);

divide_by_two(num);

return 0;

}

某天,一个刚毕业的朋友——没有贬低应届生的意思哦~~~,开始负责维护这段代码。他呢,看到num /= 2,想起课程上讲过,整数右移一位,就等于除于二,并且右移操作比除法运算要高效的多。于是将 num /=2 改为了 num = num>>1。

代码变为

#include <stdlib.h>

#include <stdio.h>

static void divide_by_two(int num)

{

while (num)
{

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

num = num>>1;

}

}

int main()

{

int num;

scanf("%d",
&num);

divide_by_two(num);

return 0;

}

编译成功后,当然不能忘了测试:

[xxx@xxx-vm-fc13 test]$
./a.out

10

10

5

2

1

[xxx@xxx-vm-fc13 test]$
./a.out

3

3

1

这位朋友对于结果很满意,于是将改动提交到了服务器,下班回家~~~

结果第二天就有同事来找他,说他的程序陷入了死循环:

[xxx@xxx-vm-fc13 test]$
./a.out

-5

-5

-2

-1

-1

-1

。。。。。。

-1

这位朋友刚参加工作,第一次提交改动,就造成了这样的结果,自然很紧张。不是右移一位就等于除以2吗?究竟是怎么回事呢?虽然暂时不知道答案,也只能将改动rollback回去。

那么到底是什么原因呢?没错,右移一位就等于除以2,但是这里需要加一个条件,这里指的是正数。而对于有符号整数,且其值为负数时,在C99标准中对于其右移操作的结果的规定是implementation-defined.

在Linux上的GCC实现中,有符号数的右移操作的实现为使用符号位作为补充位。因此-1的右移操作仍然为0xFFFFFFFF。这导致了死循环。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: