在C语言中,有过各种各样的数据类型,如:int,char ,short,long,long long,float,double等,其中,整形分为有符号和无符号。今天,我就以char类型为例子剖析C语言整型的取值范围。
测试环境为vs2010,不同的编辑器对char的定义为signed char还是unsigned char是不同的,vs2010将char定义为signed char。
#include
int main ()
{
char a = -128;
printf("%u\n",a);
return 0;
}
运行结果如下:
当我们将a的初始化的值改为128,又会发生什么呢?
#include
int main ()
{
char a = 128;
printf("%u\n",a);
return 0;
}
观察可以发现,两个程序的运行结果一模一样,那么,我提出两个问题。
#include
#include
int main ()
{
char arr[1000];
int i = 0;
for(i=0;i<1000;i++)
{
arr[i] = -1-i;
}
//求该数组的长度
printf("%d",strlen(arr));
return 0;
}
我再提出一个问题。
#include
int main ()
{
unsigned char i = 0;
for(i=0;i<=255;i++)
{
printf("hello world.\n");
}
return 0;
}
这四个问题,可以深入思考,等到文章末尾讲完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。
由于无符号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
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
当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
死循环
今天的分享就到此,喜欢的点赞加关注,下期更精彩。