用分享的方式成长,用有趣的眼光看世界。
欢迎来到12 26 25的博客 !
热爱编码、算法、知识总结,不定期更新有趣、有料、有营养内容。 让我们共同学习,共同进步。
写在前面:
近段遇到这样一个题,据说是微软面试题:
unsigned int a = 0; int b = -10;
问 a > b 是否正确 ,说说为什么
第一反应: 0 肯定大于 -10 啊,不过转念一想,微软的题不会这么脑残吧。
去IDE上运行了一下,发现确实别有洞天,发现 a>b 竟然是false, b - a 的结果是:4294967286。很诡异的一个数字,想不明白为什么会是这么个奇怪的数字。但是在我发现这数的十六进制数是FFFFFFF6时,我知道答案马上要水落石出了...
正文:
在C/C++语言中,一些数据类型的自身特性,需要特别注意,比如人尽皆知的 浮点数运算会缺失精度,而在项目编写过程中还有一个问题也是经常被有些开发者忽视,从而引起很难被察觉的BUG,就是数据类型的隐式转换
在总结转换问题之前,先说明一下各种数据类型,下表来自MSDN:
结合上表补充说明一下:
- 在32位机上,int型和unsigned int型都是32位的(4个字节),即最大为4294967295(0xffff ffff)。
- enum会跟据最大值来决定表达式最终类型,一般都是由小的类型向大的类型转换(强制类型转换除外) 如: 对于int型,如果超出int型所能表示的范围,则用比int型大的最小类型来表示(unsigned int, long 或者unsigned long)
- 而在进行操作时,应当先转化再计算
从而引出数据类型的隐式转换规则:
“ 当不同类型的数据进行操作时,应当首先将其转换成相同的数据类型,然后进行操作,转换规则是由低级向高级转换。”
如下图所示:
而C/C++在以下四种情况下会进行隐式转换:
- 算术运算式中,低类型能够转换为高类型。
- 赋值表达式中,右边表达式的值自动隐式转换为左边变量的类型,并赋值给他。
- 函数调用中参数传递时,系统隐式地将实参转换为形参的类型后,赋给形参。
- 函数有返回值时,系统将隐式地将返回表达式类型转换为返回值类型,赋值给调用函数。
最后:
经过这番总结,前面提出的问题的答案应该就很明显了,微软其实想考察的其实就是隐式转换的细节性质。
在算术运算式中 相较于常用的 char -> int ,float -> double转换,int与unsigned隐式转换却常常容易被忽略,从而产生了与负数一起参与运算时意想不到的效果。
在表达式中,a是unsigned int型,b是int型(常量整数的类型同enum),所以算术运算式b必须先转换为unsigned int型,即0xFFFFFFF6,十进制的4294967286,然后再与a计算,即 4294967286 - 0,因此结果是0xFFFFFFF6,即4294967286。
最后: 当我们进行大量编码协同开发时,有些开发者往往会忽略这样的隐式转化问题,这样是很危险的,特别是在遇到负数的情况下,int与unsigned隐式转换,所以 慎用unsigned,一定要注意隐式转换
> >
评论记录:
回复评论: