深度剖析C语言中整形的取值范围

在C语言中,有过各种各样的数据类型,如:int,char ,short,long,long long,float,double等,其中,整形分为有符号和无符号。今天,我就以char类型为例子剖析C语言整型的取值范围。



char类型的三个有趣代码

测试环境为vs2010,不同的编辑器对char的定义为signed char还是unsigned char是不同的,vs2010将char定义为signed char。

  • 第一个
#include<stdio.h>
int main ()
{
    char a = -128;
	printf("%u\n",a);
	return 0;
}

运行结果如下:
请添加图片描述
当我们将a的初始化的值改为128,又会发生什么呢?

#include<stdio.h>
int main ()
{
    char a = 128;
	printf("%u\n",a);
	return 0;
}

请添加图片描述
观察可以发现,两个程序的运行结果一模一样,那么,我提出两个问题。

  • 为什么两个程序运行结果一模一样
  • 为什么打印的是这个数字


  • 第二个
#include<stdio.h>
#include<string.h>
int main ()
{
    char arr[1000];
	int i = 0;
	for(i=0;i<1000;i++)
	{
	    arr[i] = -1-i;
	}
	//求该数组的长度
	printf("%d",strlen(arr));
	return 0;
}

运行结果如下:请添加图片描述

我再提出一个问题。

  • 为什么该数组的长度是255?


  • 第三个
#include<stdio.h>
int main ()
{
	unsigned char i = 0;
	for(i=0;i<=255;i++)
	{
	    printf("hello world.\n");
	}
	return 0;
}

运行结果如下:
请添加图片描述
死循环打印hello world.

  • 为什么for循环的每次都在接近限制条件,还是死循环了呢?


这四个问题,可以深入思考,等到文章末尾讲完char类型的取值范围,我再解答这四个问题。



signed char的取值范围

char类型有1个字节,也就是8个比特位。

下面我以二进制位来分析取值范围

00 00 00 00 ------- 0
00 00 00 01 --------1
00 00 00 02 --------2
……
……
……
01 11 11 11 --------127

到目前为止,二进制位的还是符合逻辑的,接着分析。

01 11 11 11 ---------127
10 00 00 00 ----------(-128)

这下子就有人疑惑了,127加1变成了-128?别急,听我分析。

我们注意一下,标题就已经表明,我要谈论的是signed char,也就是有符号char,那么即然是有符号的,我们的第一位便是符号位,代表的是正负,10 00 00 00,从这个方面来看,它就不是一个正数。

-128本身是一个半计算半规定的一个数字,我来分析。
首先,写出-128的原码是1 10 00 00 00 ,有人可能疑问这里为什么是9个比特位,在这里我们写的是-128的原码,而不是规定在char类型上写-128的原码。

原码:1 10 00 00 00
反码:1 01 11 11 11
补码:1 10 00 00 00

当我们存入char类型时,发生截断,即为:10 00 00 00。
观察可以发现,这不就是我们上面-128在signed char类型的补码相同吗。

而当我们对10 00 00 00这个数进行取值时,原码为:00 00 00 00,所以才有-128是一个半计算半规定的数字的说法,存的时候计算,取的时候规定为-128。

我们继续分析,signed char的取值范围。

00 00 00 00 ------- 0
00 00 00 01 --------1
00 00 00 02 --------2
……
……
……
01 11 11 11 --------127
10 00 00 00 ---------(-128)
10 00 00 01 ---------(-127)
10 00 00 10 ---------(-126)
10 00 00 11 ----------(-125)
……
……
……
11 11 11 11 ----------(-1)

总结:signed char的取值范围是-128~127。

unsigned char的取值范围

由于无符号char类型的二进制位本身就都是数值位,没有符号位,那么对unsigned char的取值范围的分析就更简单了。

00 00 00 01 ----------1
00 00 00 10 ----------2
00 00 00 11 ----------3
00 00 01 00 ----------4
……
……
……
01 11 11 11 -----------127
10 00 00 00 ----------128
10 00 00 01 ----------129
10 00 00 10 ----------130
……
……
……
11 11 11 11 -----------255

总结:unsigned char的取值范围是1~255。

各种整形的取值范围

以char为例子,我们懂得了分析某个整形类型的取值范围的方法,在分析其他整形类型时,我们就可以分为signed类型和unsigned类型,以二进制位为突破口进行分析。

解决三个代码

  • 第一个
    为什么两个程序的运行结果一模一样?

答:vs的环境下,char类型默认为signed char类型,所以取值范围是-128~127,第二个程序的a的值是128超过了取值范围,128可以看成127+1,即为-128,也就是与第一个程序的值相同。

127在内存存储为:01 11 11 11
127加一,二进制表达式加1
10 00 00 00
前面我们已经解释了该二进制位为-128

为什么打印的是该数字?

-128在内存中的存储是10 00 00 00

%u打印
需要整形提升

因为是signed char类型
发生整形提升时,补符号位,也就是1

即为11111111 11111111 11111111 10000000

该二进制的结果如下:
请添加图片描述

  • 第二个
    为什么该数组的长度是255?
    请添加图片描述

strlen函数遇到0会停止('\0’的ascall码值是0),并且不把0计入,所以长度便是-128到127,也就是255。

为什么-128变成了127呢?
程序是的循环是 -1 - i
当i为127时,-1 - i 也就是-128
当i为128时,-1 - i ,也就是-129
-129 可以看成在-128的基础上减1
-128在内存中的存储是 10 00 00 00(char类型),8个字节
-128-1,即10 00 00 00减一
也就是 01 11 11 11
也就是127

  • 第三个
    为什么for循环的每次都在接近限制条件,还是死循环了呢?

当i为0到255之前,程序并未出现问题

但当i = 255时,再进行加一
而unsigned char的取值范围为1~255
一旦255+1便超过了取值范围

255的原码 11 11 11 11
加一
1 00 00 00 00
而unsigned char只有一个字节内存,也就是8个比特位
发生截断
00 00 00 00
又变成了0
死循环

今天的分享就到此,喜欢的点赞加关注,下期更精彩。

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值