运行如下代码
int i = 10;
unsigned u = 20;
cout << i - u << endl; //输出4294967286
i -= u;
cout << i << endl; //输出-10
第一次cout输出4294967286,而第二行输出-10,为什么会有这种现象呢?
在运算i - u时,编译器会先将i强转为unsigned类型,然后再进行运算,两个unsigned类型进行运算,且结果是一个“负值”,自然会产生溢出。
而第二行是i -= u可展开为i = static_cast<int>(i - u),4294967286强转为int类型后为-10,其结果自然就正确了,不过此过程中仍存在溢出,虽然相当隐晦,但若是测试项目中开启了ubsan,这行语句就会被检测并触发crash,应当极力避免!
i -= static_cast<int>(u);
不过注意,此过程中将u强转为int类型也存在溢出风险,需自行判断数据范围是否可能导致溢出。
在int类型和unsigned类型之间的所有操作符中:加减乘除甚至比较符,均会先将int强转为unsigned再做运算。
位操作符不会有此现象。
取余操作虽不会溢出,但结果会不合预期,原因可能与有符号数和无符号数不同的存储方式有关,具体原因待分析:
unsigned u = 3;
int i = -10;
int i2 = 3;
cout<<(i % i2)<<endl; //输出-1
cout<<(i % u)<<endl; //输出0