INT_MIN
0x00 INT_MIN的值为什么不能直接表示
如果你写出下面的代码,然后使用Visual Studio编译的话,就会爆出C4146错误来。告诉你这个数字不能直接写进代码里。
1 | void check(int i) |
这是为什么呢?
编译器在处理数字-2147483648时,不会将其看做是一个数字,而是看做一个表达式,在处理时会走两步:
-
首先处理数字2147483648,这个数字超出了
int
类型的定义域,故其被临时存储成了unsigned int
类型,这在内存中是这样的:0x80000000 -
对这个
unsigned int
类型的数字2147483648作用负号,负数在计算机中使用补码表示,对0x80000000计算补码:1
2
3
4
5
6
70x80000000表示为二进制为:
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
:
1 | std::cout << (INT_MIN == 2147483648 ? "true" : "false"); |
因为后面的2147483648为unsigned int
类型,导致在比较时前面的INT_MIN
也将由signed int
升格为unsigned int
类型,最终导致他俩相等。
因此,在C/C++中,对于数字-2147483648的表述是这样的:
1 |
不直接写出其值,而是使用这样的一个减法操作来进行表述。且微软官方文档也建议在代码中使用INT_MIN
来代替直接使用其值。
0x01 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
类型来求绝对值。