我们在文章一和文章二中分析了char和uchar的取值范围和越限的情况。
总结:
1、char/uchar本质是保存的整型数,一个字节的整型数;//所谓的字符型,其实是将整型作为ascii码转换成的字符。
2、uchar的取值范围
- 十进制:0至255
- 十六进制:0至FF
3、char的取值范围
- 十进制:-128至127
- 十六进制:80至7F
4、char/uchar类型越限:
口诀:高减低加(加减256,类似十进制数的加减10,即:加减循环周期)
- 十进制:当数据高于最大上限,则减256;当数据低于最小下限,则加256;
例如:
char ch1 = 129;//129-256=-127;
char ch2 = -130;//-130+256=126;
uchar ch3=257;//257-256 =1;
uchar ch4 = -2;//-2+256= 254;
printf("%d,%d,%d,%d",ch1,ch2,ch3,ch4);
思路:32位编译器:
思路一:129-----》补码:0000 0000 0000 0000 0000 0000 1000 0001---->截取后8位1000 0001,因为是char类型,最高位是1,扩展为%d,符号位补1,1111 1111 1111 1111 1111 1111 1000 0001-》
转换为源码:1000 0000 0000 0000 0000 0000 0111 1111 ----》-127
思路二:129 = 127+2 -----》参考下图,最大的数127,顺移2个位置是-127;
思路一:-130---》补码:1111 1111 1111 1111 1111 1111 0111 1110-----》截取后8位 0111 1110,最高位为0,则使用%d(及扩展为4字节的int)显示: 0000 0000 0000 0000 0000 0000 0111 1110---》126
思路二:-130= -128-2---》参考上图,最小数,逆移2个位置为126;
思路一:257---》补码:0000 0000 0000 0000 0000 0001 0000 0001----》截取后8位:0000 0001,因为位uchar,扩展为%d,0000 0000 0000 0000 0000 0000 0000 0001---->1
思路二:257=255+2---》最大数,255顺移两个位置得1(uchar范围从0-255)
思路一:-2----->补码:1111 1111 1111 1111 1111 1111 1111 1110-------》截取后8位:1111 1110,因为是uchar,扩展为%d,符号位补0,所以是254
思路二:-2=0-2--------》顺移2个位置是254
- char的十六进制数越限(看成十进制数,char是越限了,但其实该十六进制数在80-7F之间的(1000 0000------0111 1111,这是256个数,包含了以0开头和以1开头的所有的数),并未越限)
uchar ch1 = 0xAA;
char ch2 = 0xAA;
printf("%d,%d\n%x,%x",ch1,ch2,ch1,ch2);
同样的十六进制数(也就是二进制数1010 1010),将其赋给uchar类型是170,赋给char类型是-86;无论是赋给什么值,十六进制数本身是不变的。
ps:
1)我们发现,将uchar 0xAA和char 0xAA 以十六进制形式打印出来的时候,是有区别的,原因是:
uchar, 0xAA是一个正数,相当于前面都是0,故是0xAA;
char,0xAA(10101010,其实这个数也没有越限,因为首位是1,所以是个负数,因为是在32位机上打印出来的整型占4个字节,所以,拓展为32位,前面都是F),这其实是一个短字节数转换成长字节数的问题。
2)char ch2=0xAA;以%d的形式,即以十进制形式打印出来的话,最终是多少就要将十六进制转换成十进制,然后按照“高减低加”的方式算出最多是多少。
3)对于uchar/char,如果是以一个字节的十六进制数赋值的话,我们赋值是多少,以十六进制输出就是多少(%x,无符号十六进制打印,十六进制不同于十进制的正负号%d/%u,只有无符号。),对于char/uchar,如果赋值的是一个8位的十六进制数,是不存在越限的。
所以,我们习惯于使用char/uchar来存储十六进制数,因为所见即所得。
4)对于uchar/char,我们以一个字节的十六进制数赋值,直接算的话是源码。
5)uchar的范围是从0至255共256个数,char的范围是从80至7F共256个数,相较与uchar,从80至FF从原先表示正数,现在用来表示负数。
5、当uchar/char数据为十进制数时,以十六进制形式输出的是补码形式。(当uchar/char数据为十六进制数时,以十六进制形式原样输出。)
char ch1 = 129;//129-256=-127;
char ch2 = -130;//-130+256=126;
uchar ch3=257;//257-256 =1;
uchar ch4 = -2;//-2+256= 254;
printf("%d,%d,%d,%d\n",ch1,ch2,ch3,ch4);
printf("%x,%x,%x,%x\n",ch1,ch2,ch3,ch4);
char ch5 = -127;
char ch6 = 126;
uchar ch7=1;
uchar ch8 = 254;
printf("%d,%d,%d,%d\n",ch5,ch6,ch7,ch8);
printf("%x,%x,%x,%x\n",ch5,ch6,ch7,ch8);
总总结:
1)十进制数,以十进制形式输出,“高减低加”;
2)十进制数,以十六进制形式输出,先“高减低加”,然后,转换成补码输出;
3)十六进制数,以十进制形式输出,转换成十进制数,“高减低加”输出;
4)十六进制数,以十六进制形式输出,原样输出,注意符号补位。