6.1.4 整数的范围

1.对于一个字节(8位)的整数,也就是char,可表达的数的范围:00000000-11111111.其中:

  • 00000000->0
  • 11111111~10000000->-1~-128
  • 00000000~01111111->1~127

不过这是只有整数是char类型(1个字节)的时候,如果它是别的类型的整数,它就不是-1.比如int.我们可以来试一下这件事情.

620f45b92d7d4384b90ee775f10df541.png

打印结果为-1和255.为什么.因为int有32个比特,它二进制所有的1都只填充在它最低位的字节上,它的最高位是0,所以它是一个正数.而char只有一个字节,它所有的1都填在了这8个比特上,这足以让它变成负数.即

  • int 00000000 00000000 00000000 11111111
  • char 11111111

2.接下来我们讲整数的范围.

  • char的范围是-128~127
  • short的范围是-32768(2^15)~-32767
  • int的范围是-2^(32-1)~-2^(32-1)-1
  • long的范围取决于编译器(cpu)
  • long long的范围是-2^(64-1)~2^(64-1)-1

为什么负的那边永远比正的那边多一个数呢.拿char举例,char的这一个字节能表示256个数,而这256个数分为三个部分,一个部分是负数,一个部分是0,一个部分是正数.这表明两边得少一个数,而根据补码的原则,少的这个数刚好是正数那边的,也就是有128个负数,127个正数.由此类推,负数可以到达-2^(n-1),而正数可以到达2^(n-1)-1.

3.我们已经知道,11111111被当作纯二进制看待时,它是255;而如果被当作补码看待,它是-1.同理,对于-a,其补码就是0-a,实际是2^n-a,n是这种类型的位数.其实在计算机内部,它永远都是八个1,但是你拿出来的时候怎么看它就会不一样.如果我们想要把它拿出来的时候也当作一个纯二进制来看待,那我们就需要在前面多加一个关键字unsigned.如果我们在前面这个b的char前面多加一个unsigned,会发现输出结果变为255.unsigned的意思是说,这个整数不以补码的形式来表示负数,这个整数没有负数部分,只有0和正数部分.unsigned的作用是让正数范围扩大,但是它就不能表达负数了.

如果有一个字面量,想要表达自己是unsigned,可以在后面加上u或者U.如255u.long(long)也可以用l或者L表示,而我们前面学过的float也可以用f或者F.unsigned的初衷并不是扩大数的范围,而是为了做纯二进制运算,主要是为了移位.

4.整数越界

整数是以纯二进制进行计算的,所以

  • 11111111+1->0
  • 01111111+1->-128
  • 10000000-1->127

其实他们的关系是这样子的

73f579f6218b4ee9be4521f241910f4c.png

0-1等于-1,而-1+1等于0,这很正常,我们都知道.可是到了上面这个地方127+1会变成-128,而-128-1会变成127.而如果我们用unsigned来做这件事,127+1我们会得到128,而255+1会得到0,因为256是1后面跟着八个0,而第一位的1会被丢掉,所以是全0,结果就是0.如果用0-1,我们就得到了255.

 

我们来做一个程序,算出int的最大值及其位数,代码如下:

#include<stdio.h>
int main(){
    int a=0, b=1;
    while(++a>0){
    ; 
    }
    printf("%d\n",a-1);
    while((a=a/10)!=0)
    {
        b++;
    }
    printf("%d",b);
}

上面的代码也是利用了整数越界这个特点来计算出int的最大值.

那如果我们在前面加上unsigned呢,条件应该怎么改?把%d换成%u.而如果要计算出位数,则让a=a-1再拿去循环即可.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值