C语言中整型变量的取值范围
C 语言中整型变量的取值范围
课本上第一个出现的程序就是一个求阶乘的程序,源程序如下:
#include
int factorial(int n)
{
int i,fact;
fact=1;
for(i=1;i
{
fact=fact*i;
}
return fact;
}
int main(void)
{
int m;
scanf("%d",&m);
printf("%d\n",factorial(m));
return 0;
}
在第二页出现了一个不懂的问题,课本上的描述如下:
变量都有类型(如整型int ),并在内存中占有一定的空间,例如在Visual C++中,整数变量占用4个字节的空间。因此,每个整数都有一定的取值范围。运行上述程序,输入整数13,其结果(n !)就超出了整数的取值范围,会输出一个错误的结果。
刚开始,对上面这段课本上的话我是真心看不懂的。不懂就要自己查资料。反正是在百度输入框里面尝试着输入各种关键字进行搜索,功夫不负有心人,搜索出来了。
首先,要明白计算机中的存储体系,常见的有GB ,MB ,KB 等
我们知道
1GB=1024MB
1MB=1024KB
那么,我们知道为何要用1024作为换算进度吗?
我们知道,计算机使用的是二进制,总要规定一个数作为换算进度吧,就像现实世界中我们规定以10作为长度,质量等物理量的换算进度一样,总要规定一个数吧,无论这个数是多少,终归要规定一个数作为换算单位吧,因为2的10次方等于1024,所以计算机的几位始祖一时心动,就规定了使用1024作为换算进度。
所以,一个16G 的U 盘应该是16*1024MB=16384MB=16384*1024KB=16777216KB=
16777216*1024B大小的。但是,生产储存介质的厂家,他们规定的换算进度是1000,也就是说在他们眼中,1GB=1000MB,1MB=1024KB,1KB=1024B的,所以他们生产出来的在他们眼中是16G 大小的U 盘,实际上只有16000MB=16000000KB=[1**********]B的,用电脑检测时,电脑仍然以1024为换算单位进行计算,因为[1**********]B/1024=15625000KB,15625000KB/1024=15258.789MB,15258.789MB/1024=14.901161GB,
所以,你买一个16GB 大小的U 盘,电脑最终的检测结果为却为14.3GB (不知道为何不是我上面计算的14.9GB ,可能上面的计算过程有错误,但是思路是正确的)。我的16GB 的U 盘实际大小就是14.3GB
再说一下上面的计算过程中,为何计算到B (字节)就不继续计算下去了,因为计算机对内存进行识别的最小单位也就是B (字节)了,至于后面更小的单位“位”(1字节可以储存8位二进制数,连接存储器中的8个小的电容器,电容带电和不带电两种状态对应着二进制中的0和1,这也是储存器的工作原理),计算机在识别内存时就不做识别了,所以就不用继续乘以1024了。
言归正传,继续解决本文开头的疑问,课本中的那段话中有这样一句:“例如在Visual C++中,整数变量占用4个字节的空间”,我查资料后知道,变量占几个字节的空间是由编译器(就是编程序的那个软件)决定的,咱们使用的是Visual C++ 6.0 也是Visual C++的版本之一,所以咱们写程序时,定义的整型变量的取值范围就是4个字节的内存大小所能表示的最大值到最小值之间的范围。
我们会理所当然的这样想:1个字节可以储存一个8位的二进制数(就是一组由8个0或1组成的一个二进制数),连接存储器中的8个小的电容器,每个电容器有带电和不带电两种状态,那么,以此计算,4个字节连接的就有了32个电容器,每个电容器有两种状态,共可表示2的32次方组数据,每组数据中有32个0或1组成,相应的4个字节也就能表示2的32次方个数据了。所以,用Visual C++定义一个整型变量,它的取值范围就应该是0到pow(2,32)-1了。
其实不然,我们忘了,定义的整型变量是可以取负数的,所以,在32个电容器中(也叫32位),我们会选取一个电容器,规定它的两种状态分别表示符号的正负(也就是所谓的“最高位为符号位,最高位为1时说明是负数,最高位为0时说明是正数”),这样也就剩下了31个电容器,所以我们定义的整变量的实际取值范围为:【负的pow(2.31)到负1】交上【0到正的pow(2,31)-1】 每个集合都包含端点的两个数据,所以每个集合内都有pow(2,31)个数,共有pow(2,32)个数。
下面是验证阶段,我们知道pow(2,31)=2147483648,所以做如下验证:
打开软件Visual C++ 6.0
运行下面的程序
#include
int main(void)
{
int a,b,c;
a=2147483647;
b=a+1;
c=b+1;
printf("%d\n%d\n%d\n",a,b,c);
return 0;
}
程序结果如下
可以看出,a=pow(2,31)-1,在整型变量的取值范围内,所以a 的运行结果正常,而b 和c 的运行结果就异常了。同时,也可以知道,当数据超出所定义变量的取值范围时,编译器是不会报错的,只会输出一个错误的数据。验证过程证明了上述推断的正确性。
类似的,在Visual C编译器中,编译软件规定的是整型变量占用的是2个字节的空间。所以,它定义的整型变量的取值范围因该是【负的pow(2,15)到负1】交上【0到正的pow(2,15)-1】 因为我没有VC ,所以无法验证,但应该是这样的。
问题解决了,弄懂了,本来就开关两种状态,你非要表示三个数据,咋会不输出一个错误的结果呢。