如果你写出下面的代码,然后使用Visual Studio编译的话,就会爆出C4146错误来。告诉你这个数字不能直接写进代码里。
void check(int i){if (i > -2147483648) // 爆出错误:C4146// do somethings}
这是为什么呢?
编译器在处理数字-2147483648时,不会将其看做是一个数字,而是看做一个表达式,在处理时会走两步:
首先处理数字2147483648,这个数字超出了int
类型的定义域,故其被临时存储成了unsigned int
类型,这在内存中是这样的:0x80000000
对这个unsigned int
类型的数字2147483648作用负号,负数在计算机中使用补码表示,对0x80000000计算补码:
0x80000000表示为二进制为:1000 0000 0000 0000 0000 0000 0000 0000其反码为:0111 1111 1111 1111 1111 1111 1111 1111由补码=反码+1得:补码=1000 0000 0000 0000 0000 0000 0000 0000将其转换为16进制恰好又等于0x80000000
得到的结果恰巧还是2147483648。这就导致-2147483648在实际计算时变成了2147483648。
同理,这也导致了下面的代码将会输出true
:
std::cout << (INT_MIN == 2147483648 ? "true" : "false");
因为后面的2147483648为unsigned int
类型,导致在比较时前面的INT_MIN
也将由signed int
升格为unsigned int
类型,最终导致他俩相等。
因此,在C/C++中,对于数字-2147483648的表述是这样的:
#define INT_MIN (-2147483647 - 1)
不直接写出其值,而是使用这样的一个减法操作来进行表述。且微软官方文档也建议在代码中使用INT_MIN
来代替直接使用其值。
INT_MIN
的绝对值怎么求,用abs
函数吗?如果我们用abs
函数求解INT_MIN
的绝对值的话,返回结果仍是INT_MIN
,这是因为abs
函数返回值的缘故,abs
函数输入一个int
,返回一个int
。而INT_MIN
的绝对值等于INT_MAX+1
,这样,超出int
类型的定义域后的那个加1将会其值重新变为INT_MIN
,这就导致了INT_MIN
的绝对值还等于INT_MIN
的情况。所以,此处我们需要使用llabs
函数来将其强制转化为long long
类型来求绝对值。