有符号 & 无符号!改变计算结果的陷阱!


简单的代码,复杂的问题。
环境:VC6SP5,Win2kPro

int b = 10; //已经赋值为有效数据
const char * str = "1234567890ABCDEF"; //已经赋值为有效的字符串。
int a = (b - strlen(str) ) / 2;

经过了这样的计算,a的值究竟是多少?
结果当然不是 (10-16)/2 的 -3,而是一个天文数字。。。。
a = 2147483645 或者,16进制的 0x7ffffffd

真正的问题代码只有一行,但是结果却令人不快。

这里分析一下产生这个问题的原因:
一个隐含的问题是,strlen的返回值,类型是size_t,也就是unsigned int。这是个无符号类型。
当unsigned int 和 int混合运算的时候,编译器会认为,unsigned int的表达长度比较长,因而结果的类型是unsigned int。
所以 b - strlen(str) 的结果不是 -6,而是和-6具有相同内存布局的unsigned int 值:0xfffffffa,也就是正的4294967290
如果这个数值直接赋值给int,会因为内存布局相同,而避免问题的产生--问题存在,但是不产生不良效果。但是随后的/2操作把问题彻底暴露出来了。。
/2操作可以认为是一次移位,对于无符号类型,移位后高位补0,于是把原本有符号类型赖以利用的符号位清零了。。最终这个数值赋值给int类型的时候,结果就变成了前面提到的那个可怕的数值。。

有符号数字和无符号数字混合运算的时候,存在一些默认的转换规则,符合这些规则的转换,都不会引发编译器警告或者错误,因此这类问题是难以觉察的。但是,我们需要经常使用的库函数太多了,当参与运算的时候,为每个函数调用都指定一个固定类型的返回值,似乎是不可能的任务。因此如果你的程序中充满各种不同类型的整型运算,那么还是尽量小心一些吧。。。

posted on 2008-04-16 09:02 RedLight 阅读(1108) 评论(2)  编辑 收藏 引用 所属分类: C++功夫篇

评论

# re: 有符号 & 无符号!改变计算结果的陷阱! 2009-01-06 06:11 AlexEric

但也仅仅是出现负数的时候是这样的吧...  回复  更多评论   

# re: 有符号 & 无符号!改变计算结果的陷阱! 2009-04-28 09:32 dfa

这种问题需对隐式转换法则有所了解   回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年7月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

公告


Name: Galen
QQ: 88104725

常用链接

留言簿(3)

随笔分类

随笔档案

相册

My Friend

搜索

最新评论

阅读排行榜

评论排行榜