今天同事有个问题,基本情况就是当
Operator
在
GUI
界面操作输入了一个非法值(例如一个负值),居然没有任何错误提示,导致最后
log
中记录的信息让人无法理解。从信息的处理流程来看,没有任何问题。后来发现是因为程序中有一个计算步骤是用一个
unsigned int
和输入的数值作了一个相加,然后再对计算结果大小进行判断。由于输入的是负数,负数和
unsigned int
做算术运算时,被自动转换为了一个大整数,计算的结果肯定也不正确了。
这让我想到了曾经的一个笔试题,大概是这样的:
下面的程序的结果是什么
:
int
fun() {
unsigned int a = 10 ;
int b = - 100 ;
int c;
(a + b > 0 ) ? (c = 1 ):(c = 0 );
return c;
}
unsigned int a = 10 ;
int b = - 100 ;
int c;
(a + b > 0 ) ? (c = 1 ):(c = 0 );
return c;
}
正确答案:
1
。原因就是
int b
本身是有符号书
-100
。但是当它和无符号整数
a
做计算时,他就被自动转化为无符号整数了。也就是说,本身
-100
是:
0xffffff9c
,符号位为全
1
。但是作为无符号数,
-100
就成为一个硕大的正整数(好像是
18446744073709551516
),因此
a+b
得到的结果也是一个硕大的正整数。
问题解决了,那就回忆一下
C/C++
里面数据类型自动转换的规则:
1
,表达式中,所有小于整型的有序类型的变量在计算之前都会被转换成整型。
char
和
short
类型的值,无论有无符号,在计算时都自动转换成
int
或者
unsigned int
。
enum
类型也同样。
2
,表达式中的数据如果遇到更高级别的数据,就会自动转换为高级别的数据类型。如果我们“定义”一个数据类型表示的范围越大,这个类型的级别越“高”。那么按照从高到低的顺序排列,应该是:
long double > double > float > unsigned long long > long long > unsigned long > long > unsigned int > int
(注意,有的系统中,
long
和
int
大小相同,此时
unsigned int
的等级就会高于
long
)。
3
,赋值语句中,等号右边的值会在运算之前自动转换为等号左边变量的数据类型,然后才开始计算。这个过程可能导致右边的值转为级别更高的数据类型,也可能“降级”。通常“降级”的时候,编译器都会给一个
warning
提示数据可能会被截断。
4
,对于函数,在参数传递时,传入的数据类型会转换为形参的类型;返回的时候,返回的表达式类型也会自动转换为函数返回类型。
5
,类型转换改变的是值得类型,而不是对象的类型。例如开头的例子中,只是在计算的时候将
-100
的值变为
unsigned int
来计算,本身
a
这个变量没有变!
以上是小弟的总结,能力有限,如有不对之处,敬请原谅并指正。