负数取反,单目运算“-”的运算

首先看代码:

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

原文地址:https://www.cnblogs.com/xiaodingmu/p/8215613.html