本博客讲解char的整型提升与char类型数据在%d与%u格式下的打印结果,想了解short的整型提升也可以看,因为两种提升的原理相同。废话不多说,开讲!!!
1.整型提升的概念
整型提升是C程序设计语言中的一项规定:在表达式计算中,各种整型要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型;然后执行表达式的结果。(coming from百度百科)
由于char所占字节不足4,所以在运算或打印时先要进行整型提升
2.整型提升的分类
(1)有符号位:有符号位的整型数据在整型提升时要求符号位(最高位)不变,前面待补位全部补上符号位。总之,负数补1,正数补0;
(2)无符号位:无符号位的整型数据在整型提升时要求前面待补位全部补上0即可。
3.原码--反码--补码
在正式讲解整型提升前,我觉得非常有必要讲一下三码。一般而言,在整型中有符号数的正数与无符号数在内存中存储时三码相同,而有符号数中的负数在内存中存补码。
4.整型提升的步骤
(1)将整型数据转化int类型下的内存存储形式,这里以-1为例,(注意这里无需关心数据的类型),比如char a=-1与unsigned char a=-1,它们的数据转化都一样:
10000000000000000000000000000001-- -1的原码
1111111111111111111111111111111111110-- -1的反码
1111111111111111111111111111111111111-- -1的补码
因为负数在内存中存补码,所以其存储形式为11111111111111111111111111111111
(2)得到该数据在其数据类型中的存储形式:
由于char与unsigned char类型占一个字节,所以它们的数据在存储时要截取int类型存储形式的后八位,因此-1在char与unsigned char类型中的存储形式是11111111
(3)start整型提升
{1}有符号位的整型提升
由于char代表有符号位类型,而且11111111的最高位是1,所以待补位全补1
11111111->11111111111111111111111111111111
{2}无符号位的整型提升
由于unsigned char代表无符号位类型,所以待补位全补0
11111111->00000000000000000000000011111111
(4)不同打印格式下的不同结果
{1}%d--打印有符号位的十进制整型数
由于11111111111111111111111111111111的最高位是1,是负数,而负数在内存中存补码,欲得其值先补转原:
11111111111111111111111111111111--补码
11111111111111111111111111111110--反码
1000000000000000000000000001--原码
最终打印结果为-1;
{2}%u--打印无符号位的十进制整型数
由于无符号数三码相同,所以由00000000000000000000000011111111直接得出结果为255
5.精算例题讲解----带你实战一波
例一:
int main()
{
unsigned char a =-1;
printf("%d %u", a, a);
//答案: 255 255
return 0;
}
//11111111-- -1在unsigned char中的存储形式
//整型提升后,见下
//00000000000000000000000011111111--整型提升后无符号数三码相同,所以无符号数的两种打印格式的结果相同
例二:
int main()
{
char a = 32;
//10000000-a在char类型中的存储形式
//a是有符号类型数据,整型提升后,见下
//111111111111111111111111100000000-补码,也是a整型提升后在内存中的存储形式
//111111111111111111111111011111111-反码
//100000000000000000000000100000000-源码
printf("%d %u",a,a);
// 答案: -128 4294967168
//可见由于a在char数值范围内的%d打印结果是其本身,即-128->127
return 0;
}
例三:
int main()
{
int i;
char a[1000];
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
//printf("c=%d", strlen(a));
//求c的值
//数组a的元素是char类型,每一个元素占一个字节
//i:0->999时,a的元素:-1 ->-1000;
//看到这里,大家是不是觉得答案就是1000呢?错了,听我开讲。
//我们知道i从0到127时,a[i]的值都是其本身,可是从a[128]=-129开始,你们看看它们的结果
printf("%d %d %d %d %d", a[128], a[129], a[254], a[255] , a[256]);
// a[128]=127 a[129]=126 a[254]=1 a[255]=0 a[256]=-1
//看到没,i从128到256时,a[i]的结果居然循环了
//而strlen函数是用于打印字符串长度的,一旦碰到'\0'便会停止打印(所打印的长度不包括'\0'),而'\0'的ASII码值为0,
//所以strlen打印字符串一直到a[255]=0,所以答案结果为c=255;
return 0;
}