编写安全代码——小心有符号数的右移操作
2013-10-12 22:02
204 查看
转载来源:http://blog.chinaunix.net/uid-23629988-id-3018793.html
作者: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。这导致了死循环。
---------------------------
补充:
其实也说明另外一个问题:测试不充分,针对int类型参数,一定要测试完整样本数据。
作者: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。这导致了死循环。
---------------------------
补充:
其实也说明另外一个问题:测试不充分,针对int类型参数,一定要测试完整样本数据。
相关文章推荐
- 编写安全代码——小心有符号数的右移操作
- 编写安全代码——小心有符号数的右移操作(转载)
- 编写安全代码——小心有符号数的右移操作
- 编写安全的代码——小心有符号数的右移操作
- 编写安全代码:小心使用浮点数
- 编写安全代码:小心volatile的原子性误解
- 编写安全代码:小心volatile的原子性误解
- 编写安全代码:小心volatile的原子性误解
- 编写安全代码:小心使用浮点数
- 编写安全代码:有符号数和无符号数的移位区别
- 编写安全代码:有符号数和无符号数的移位区别---右移
- 编写安全代码:小心使用浮点数
- 编写高质量代码改善C#程序的157个建议[泛型集合、选择集合、集合的安全]
- 内存管理---编写安全的代码的一些技巧 C++
- 编写安全代码:再论整数类型转换
- 写高质量OC代码52建议总结:32.编写“异常安全代码”时留意内存管理问题
- 不安全的代码: 教你“随心所欲”地在内存中操作Java的类和对象(4)
- 检查代码是否存在整数操作安全漏洞
- 编写异常安全的代码永远不会亏本
- 编写安全的Symbian C++游戏代码