c语言中存储整型数据越限分析

1、每种数据类型存储的数据是有范围的,故超出该范围,数据会越限,造成数据错误。

例如:

int类型,占用4个字节,其范围是从-2147483648~2147483647

(为何是此范围,详见C语言中源码和补码详解_modi000的博客-CSDN博客_c语言源码补码

上述为十进制范围,化为十六进制范围 0x8000 0000~0x7fff ffff

十进制十六进制二进制实际打印及存储
-10x8000 00011000 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 

21474836470x7fff ffff0111 1111 1111 1111 1111 1111 1111 1111

二进制:0111 1111 1111 1111 1111 1111 1111 1111

十六进制:0x7fff ffff

总结:无论是正整数还是负整数, 存储的都是补码,只不过是正整数的补码是他本身;

正整数/负整数打印输出十进制数,显示其源码。

正整数/负整数打印输出十六进制数,显示其补码。

例如:

int a = -1;//源码:1000 0000 0000 0000 0000 0000 0000 0001

printf("%x\n",a); //输出的是补码:ffff ffff

因此,在整型出现越限后,判断越限后的结果是多少,需要先转换成二进制补码来看。

例1:

int  a = 2147483648;

printf("%x\n",a); //输出的是8000 0000 

printf("%d\n",a); //输出的是-2147483648 

分析:注意:越限情况下,符号位需要多出来一位,如int型,此时符号位是在第33的位置上,然后按照这种形式算补码

二进制补码是: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

分析:注意:越限情况下,符号位需要多出来一位,如int型,此时符号位是在第33的位置上。

二进制源码是: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后,会变成第二大的正数,依次类推。

 

 

计算越限后值的步骤:

1)根据十进制数的正负情况在最高位前面一位添加符号位并转换成二进制数,正数,符号位为0,负数,符号位为1;

2)根据添加后的值情况 (包括新加的符号位)来计算补码,正数,不变;负数,取反加1,求补码;

3)去掉添加的符号位,获得最终计算机存储的数值,此数值的最高位为1,则取反加1转换为负整数,为0直接转化成十进制正数。

补充一种新的越限思路:

int  a = 2147483648;  看成是2147483647 + 1;

也即:0x7f ff ff ff +1 = 0x80 00 00 00 // 是-2147483648 的补码;

int  a = -2147483649;看成是-2147483648 -1;

也即:0x80 00 00 00 -1 = 0x7f ff ff ff //2147483647 的补码也是源码;

另外:对于无符号的数据类型越限的情况  unsigned char ch;范围是0-255;

unsigned char ch = 256;看成是255 +1;

也即:0xff +1 =  0x00(进位为1,舍去),故输出为0;

unsigned char ch = -1;看成是 0 -1;

也即:0x0 -1 = 0xff(从高位借位),故输出为255;

出现一个有趣的现象:

unsigned char ch = 255;

ch++;  //ch =0;

ch--;// ch =255;

小结:发现unsigned 同 signed数据类型一样,越位后的值也是个循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值