以C程序角度探究计算机里int 类型的存储与最大数最小数,为什么负数补码存储

来源:互联网 发布:金博软件 编辑:程序博客网 时间:2024/05/13 18:19

一c语言运算int最大值,最小值

   首先我们写这样一个程序,让计算机自己计算能存储的最大值。

PS:我采用的是GCC编译器,在CODEBLOCK环境下调用gcc编译的。(我的计算机intel core i5处理器,32位win7操作系统)

给s赋一个初值,取得比较大,因为太小的话,程序运行时间很长。当然这样有点事后诸葛亮的嫌疑,最好是赋值为1,但是运行时间太长。有兴趣可以自己试一下。

代码如下

int main(){    time_t start,end;start=clock();int s=2147400000;//为什么初值取这么大呢?因为太小,运算时间太长while(1){   tt: s+=1;    printf("值=%d\n",s);      if(s<0) {printf("int数据最大值=%d\n",s-1);     break;     }      if(s>0)      goto tt;}end=clock();printf("程序运行时间为:%lf\n秒",difftime(end,start)/CLOCKS_PER_SEC);return 0;}


运算结果如下

 

 

由此可以知道最大值是2147483647.

下面我们写一个类似的程序,来输出int类型最小负数。

 

int main(){//计算最小值    time_t start,end;start=clock();int s=-2147480000;//为什么初值取这么大呢?因为太小,运算时间太长while(1){   tt: s-=1;    printf("值=%d\n",s);      if(s>0) {printf("int数据最小值=%d\n",s+1);     break;     }      if(s<0)      goto tt;}end=clock();printf("程序运行时间为:%lf\n秒",difftime(end,start)/CLOCKS_PER_SEC);return 0;}

运行结果如下

 

由此我们知道最小值就是我们在第一个计算最大值的时候,溢出的第一个负数。

二:关于最大值,最小值的进一步测试

1:首先我想知道,我采用的编译环境下,int类型采用几个字节存储。

sizeof(int)可以告诉我结果,是4个字节,32位。

2:最大的数,是不是采用0xffff ffff ffff ffff表示的呢?我也想知道,所有测试下。

3:计算机存储负整数,最高位是符号位,来区分正整数负整数,那么0x8000 0000 0000 0001是表示-1么?

这是我想知道的问题,所以写下列程序测试。

代码如下:

#include <iostream>//计算机里int类型的存储与数据范围,溢出问题using namespace std;int main(){    cout<<"int类型占用字节"<<sizeof(int)<<endl;//判断当前编译环境下int存储的字节数,输出为4,4字节,32位    int i=0x00000001;   //定义一个int类型变量,32位    cout<<i<<endl;    i=i<<1;          //左移一位,正常,无溢出    cout<<i<<endl;    //最大的数是不是0xffffffff呢?输出看一下就知道    i=0xffffffff;    cout<<"0xffffffff表示的数是最大整数么?i="<<i<<endl;   //输出结果是-1(如果你学习过计算机原理,负数二进制表示换算成十进制,全部取反,+1)    //最大整数是多少?    int j=0x80000001;    cout<<"j=0x80000001是-1么?j="<<j<<endl;    i=0x7fffffff;         //最大正数范围,0b0111 1111 1111 1111    cout<<"0x7fffffff表示的数="<<i<<endl;    j=i+1;    cout<<"0x7fffffff+1表示的数="<<j<<endl;            //+1之后溢出,0x80000000    i=0x80000000;              //最高位是1,符号位,其余31位都是0,取反31位都是1,再加上1,0x    cout<<"0x80000000表示的数="<<i<<endl;            //最小值    i=i-1;    cout<<"0x80000000减去1="<<i<<endl;    return 0;}

运行结果如下
告诉我们很多信息。int是4个字节。0xffff ffff ffff ffff并不是最大正数,0x8000 0000 0000 0001也不是-1。

原来0x7fff ffff  是最大正整数.

0xffff ffff  是-1最大负整数。

0x8000 0000是最小负数。

 

三:计算机存储0x80000001为什么不表示-1?

如果我们采用0x8000 0001表示-1,那么我们在与正整数相加时候会遇到这样的问题。

例子:-1+1=0

 

 

0000 0000 0000 0000 0000 0000 0000 0001

1

+

8000 0000 0000 0000 0000 0000 0000 0001

-1

=

8000 0000 0000 0000 0000 0000 0000 0010(-2)

0

这样的计算与正整数不相同。

正常的正整数相加的运算规则不适用于正整数与负整数的加法,因此必须制定两套运算规则,一套用于正整数加正整数,还有一套用于正整数加负整数。从电路上说,就是必须为加法运算做两种电路。

在第二部分,我们用C语言程序,测试知道。0xffff ffff表示的是-1-10xffffffff1相加运算

 

 

0000 0000 0000 0000 0000 0000 0000 0001

1

+

1111 1111 1111 1111 1111 1111 1111 1111

-1

=

0000 0000 0000 0000 0000 0000 0000 0000(进位是1,舍弃)

0

 

这样的运算就正确。在计算机里,我们就可以采用一种电路来计算,正整数相加,正整数与负整数相加。这样的话,规则通用,一套加法电路就可以了。

这种在现有计算机体系中采用的负整数的表示方式,称为补码表示法。0xffff ffff最高位是符号位,其余位全部取反就是0x80000000 ,这个数再加1,就是0x8000 0001,就是-1.

对于所有的负整数,我们都可以采用这样的补码规则得到它实际表示的数。

至此,我们可以清楚了计算机里int类型的存储方式,及范围大小。

 

 

0 0
原创粉丝点击