首先看代码:
int main(){ int i=-2147483648; return printf("%d,%d,%d,%d",~i,-i,1-i,-1-i); }
输出结果为:
2147483647,-2147483648,-2147483647,2147483647
这里就涉及到对负数取反,单目运算符“-”的理解,在int占4个字节,大小范围为-2147483648~2147483648,最高位代表符号位,所以第32位为1,这里就需要理解计算机中负数的表示形式:
计算机中的数字都是以补码的形式存放!
正数的原码、反码、补码都相同
5在计算机中原码、反码、补码均为:00000000 00000000 00000000 00000101
负数的反码为对该数的原码除符号位外各位取反,补码为其反码加1:
-5原码为:10000000 00000000 00000000 00000101
反码为:11111111 11111111 11111111 11111010
补码为:11111111 11111111 11111111 11111011
所以-5在计算机中存储形式为11111111 11111111 11111111 11111011转换为十六进制为:0xFFFFFFFB
但是-2147483648比较特殊!
-2147483648原码为:10000000 00000000 00000000 00000000 (表示-0)
反码为:11111111 11111111 11111111 11111111
补码为:00000000 00000000 00000000 00000000
+0的原码、补码、反码均为00000000 00000000 00000000 00000000
如果用-2147483648用补码00000000 00000000 00000000 00000000来表示则和0的补码一样,不能区分开;
所以计算机规定用10000000 00000000 00000000 00000000来表示-2147483648的补码,
32位最小负整数的补码为10000000 00000000 00000000 00000000
计算机中-2147483648取反为:01111111 11111111 11111111 11111111,此为存储正数的补码,换算原码得到数为2147483647
单目运算符“-”为取负,-2147483648取负为2147483648,显然超过int类型范围(-2147483648~2147483647),刚好超过一个就变为-2147483648,所以其对应的补码仍为10000000 00000000 00000000 00000000,
对应补码理解就是-x=~x+1;即补码取反加1,10000000 00000000 00000000 00000000取反加1后任然为10000000 00000000 00000000 00000000,对应数为-2147483648
1-i为(-i)+1,对应补码为:
10000000 00000000 00000000 00000000+00000000 00000000 00000000 00000001=10000000 00000000 00000000 00000001
转换为十进制为:- 2147483647
-1-i为(-i)+(-1),对应补码为:
10000000 00000000 00000000 00000000+11111111 11111111 11111111 11111111=01111111 11111111 11111111 11111111
转换为十进制为: 2147483647
其实也可以从十进制理解:-2147483648-1=-2147483649,超过范围后变为2147483647