char类型存储的分析
char和signed char
大家对char类型相信一定不会陌生的ANSI C 提供了3种字符类型,分别是char、signed char、unsigned char
char相当于signed char或者
unsigned
char,但是这取决于编译器!
这三种字符类型都是按照1个字节存储的,可以保存
256个不同的值。
signed char取值范围是 -128 到 127
那么问题来的为什么signed char的取值范围是从 -128到127呢
首
先大家应该知道原码反码补码的概念以及他们之间的关系。
------------------------------------------------------------
正数的原码、反码和补码相同
负数将原码先进行除符号位取反然后再加一就可以得到他的补码
------------------------------------------------------------
现在继续,首先上面提到char可以保存256个不同的值,也就是说明他的二进制编码只能拥有8位有符号
的char占一个字
节,
最高位表示正负,其余的七位表示数值,七位二进制可以表示128个数(2^7 =
128)
,即0~127;加上符号位后,就
变成
了-127~-0,0~127,但是我们实际上char的取值范围为 -128~127,这时就会发现这个-0是什么东西,聪明人一眼就
能
看
出
来-0
和 -128有关系。。(当然不能瞎猜,我们要用事实
来证明)
首先呢计算机是以补码形式存储的
我列出-0和-128的原码反码补码
-0 原码 1000 0000
反码 0111 1111
补码 1000 0000
-128 原码 11000 0000
反码 10111 1111
补码 11000 0000
可以看出来这个其实根本不是-0,只是因为char类型只能存储8位二进制编码,而-128有9位,所以只能将他前
面的1截掉
,所以给了
你一个错觉-0,这东西完全就是不存在的,你要记住他只是-128没有被截掉的那部分,但
是它还是属于-128。
unsigned char 取值范围是 0 到 255 但是char究竟相当于signed char呢还是相当于unsigned char呢??
这就是char和int的不同之处!
int==signed int,但是char不能简单以为==signed char
以我的编译器为例子
他们的值完全不同,但是为什么呢。
首先列出-1的原码反码补码
-1 原码 1000 0001
反码 1111 1110
补码 1111 1111
当为signed时可以看出来值为-1,但是当它为unsigneds时计算机只识别补码序列然后值就为255.
下面做两个小练习
1==》
#include<stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
现在看结果
其实第一次我看到这个心情也是日了狗了。。。。
完全解释不通。。。。。
我简单说一下我的理解,如果错了指出来,我们已经知道了-128的补码序列,现在把它提出来(1000 0000 ),但是你是
希望计算
机以%u的形式打印出来,所以你要对-128的补码形式进行扩展(整形提升),把它扩展成32位,由于扩展是根据你
自身的符号位扩
展,所以你往
它的前面加上24个1。然后%u他只是拿到你的序列将它打印出来,所以
他就打印出来我们
刚
刚
扩展出来的2进制序列,
也就是上面的
值。
-128 整形提升后补码形式:
1111 1111 1111 1111 1111 1111 1000 0000
还有这里的%u,我们都应该知道数据在内存中是以补码形式存储的,现在%u输出也就是认为你就是无符号数,所以在%u的
角度来
讲,它直接从你的内存中拿出来的就是原码,直接输出内存中拿出来的数据.
2==》
我们再来看一个题
#include<stdio.h>
intmain()
{
char a = 128;
printf("%d\n",a);
return 0;
}
看看结果:
这里我明明要%d要打印的是128,为什么打印出来-128.编译器坏掉了?
其实这里当你使用了%d还是发生了整形提升了,128的补码序列(1000 0000)
对它进行整形提升后是这样的
补码: 1111 1111 1111 1111 1111 1111 1000 0000
反码: 1111 1111 1111 1111 1111 1111 0111 1111
原码: 0000 0000 0000 0000 0000 0000 1000 0000
那么这个序列认识么? 前面不用看它的类型时char类型,所以在char中128是不存在的,然后char的取值范围是
127 ~ -128,所以
这里直接跳到
char取值范围最小的-128去。