1、每种数据类型存储的数据是有范围的,故超出该范围,数据会越限,造成数据错误。
例如:
int类型,占用4个字节,其范围是从-2147483648~2147483647
(为何是此范围,详见https://blog.csdn.net/modi000/article/details/103882926)
上述为十进制范围,化为十六进制范围 0x0x8000 0000~0x7fff ffff
十进制 | 十六进制 | 二进制 | 实际打印及存储 |
-1 | 0x8000 0001 | 1000 0000 0000 0000 0000 0000 0000 0001 | 二进制:1111 1111 1111 1111 1111 1111 1111 1111 十六进制:0xffff ffff |
-2147483648 | 二进制:1000 0000 0000 0000 0000 0000 0000 0000 十六进制:0x8000 0000 |
||
2147483647 | 0x7fff ffff | 0111 1111 1111 1111 1111 1111 1111 1111 | 二进制:0111 1111 1111 1111 1111 1111 1111 1111 十六进制:0x7fff ffff |
总结:无论是正整数还是负整数, 存储的都是补码,只不过是正整数的补码是他本身;但是显示的十进制数,是其源码。
例如:
int a = -1;
printf("%x\n",a); //输出的是ffff ffff
因此,在整型出现越限后,判断越限后的结果是多少,需要先转换成二进制补码来看。
例1:
int a = 2147483648;
printf("%x\n",a); //输出的是8000 0000
printf("%d\n",a); //输出的是-2147483648
分析:
二进制补码是:0 1000 0000 0000 0000 0000 0000 0000 0000
只有32位,所以存储的是后32位,也就是-2147483648的补码。
例2:
int a = 2147483649;
printf("%x\n",a); //输出的是8000 0001
printf("%d\n",a); //输出的是-2147483647
分析:
二进制补码是:0 1000 0000 0000 0000 0000 0000 0000 0001
只有32位,所以存储的是后32位,也就是-2147483647的补码。
例3:
int a = -2147483649;
printf("%x\n",a); //输出的是7fffffff
printf("%d\n",a); //输出的是2147483647
分析:
二进制源码是:1 1000 0000 0000 0000 0000 0000 0000 0001
二进制补码是:1 0111 11111 1111 1111 1111 1111 1111 1111
保留后32位,结果为2147483647
例4:
int a = -2147483650;
printf("%x\n",a); //输出的是7ffffffe
printf("%d\n",a); //输出的是2147483646
分析:
二进制源码是:1 1000 0000 0000 0000 0000 0000 0000 0010
二进制补码是:1 0111 11111 1111 1111 1111 1111 1111 1110
保留后32位,结果为2147483646
总结:int型变量,正数越限1后,会变成最小的负数,越限2后,会变成倒数第二小的负数,依次类推。
负数越限1后,会变成最大的整数,越限2后,会变成第二大的正数,依次类推。