1.对于一个字节(8位)的整数,也就是char,可表达的数的范围:00000000-11111111.其中:
- 00000000->0
- 11111111~10000000->-1~-128
- 00000000~01111111->1~127
不过这是只有整数是char类型(1个字节)的时候,如果它是别的类型的整数,它就不是-1.比如int.我们可以来试一下这件事情.
打印结果为-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
其实他们的关系是这样子的
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再拿去循环即可.