左图无符号unsigned char的数值图,可知,是由0~255。
右图是有符号char(char和 signed cahr)的数值图,可知是由 -128~127。
截断:
将一个整数存储到char里面,由于char是一个字节大小,对于四个字节大小的整数,会发生截断,只保留补码的最后8位。
整形提升:
意义在于将截断后的8位补充到32位,
规则:对char和signed char(有符号char)这种有符号位的采用左补24个符号位(截断后的8个比特位的符号位)。
对unsigned char 这种无符号位的采用直接左补24个0。
整形提升后的打印;
一:%u
%u是以无符号的形式打印整数,所以,我们整形提升后得到的32位补码直接可以作为原码 ,再打印出结果。
二:%d
%d是以有符号的形式打印整数,所以,我们整形提升后得到的32位补码,要先观察32的第一位,如果是1,则是负数,需要将这32位补码转化为原码(-1,符号位不变按位取反);如果是0,则是正数,原返补码相同,直接打印即可。
重点:整形提升需要注意char是否有无符号,但是提升完毕后,不管是%d,还是%u打印,都不需要在考虑char是否有无符号,而是要站在%d和%u的角度去考虑整形提升后的32位是直接打印(%u),还是要从补码换成原码(%d)。
题目讲解:
1.
//
输出什么?
#include <stdio.h>
int
main
()
{
char
a
= -
1
;
signed char
b
=-
1
;
unsigned char
c
=-
1
;
printf
(
"a=%d,b=%d,c=%d"
,
a
,
b
,
c
);
return
0
;
} //a=-1,b=-1,c=255
首先abc截断后的8位都是一样的(1111 1111),其次a,b都是有符号char,所以a,b的整形提升后的32位一样(1111 1111 1111 1111
1111 1111 1111 1111
),又都是按照%d打印,32位要转化成原码,符号位为1,所以为负数,原码为 (1000 0000 0000 0000 0000 0000 0000 0001),结果就是-1。
对于c,
截断后的8位都是一样的(1111 1111),整形提升无符号char,所以左补24个0,此时32 位为(0000 0000 0000 0000 0000 0000 1111 1111),要以%d打印,第一位为0,所以是正数,原反补相同,直接作为原码打印,255。
2.
#include <stdio.h>
int
main
()
{
char
a
= -
128
;
printf
(
"%u\n"
,
a
);
return
0
;
}//4294967168
a截断后为(1111 1111),整形提升,有符号char左补符号位,所以32个1,又以%u打印,所以,直接补码打印即可。
3.
unsigned int
i
;
for
(
i
=
9
;
i
>=
0
;
i
--
)
{
printf
(
"%u\n"
,
i
);
} //从9~0然后从4294967168递减。
从9~0很简单,当-1的时候,补码全为1,而%u打印,补码直接打印,所以结果为4294967168,然后再递减1。
4.
int
main
()
{
char
a
[
1000
];
int
i
;
for
(
i
=
0
;
i
<
1000
;
i
++
)
{
a
[
i
]
= -
1
-
i
;
}
printf
(
"%d"
,
strlen
(
a
));
return
0
;
}//结果为255
char的范围在-128~127,a【i】从-1递减开始1(-1,-2,-3)到-128,然后由图可知会从,127到0,总的来说,从-1~-128,然后从127~0,而strlen的判断条件是‘\0’,‘\0’的ascll码值就是0,所以在a【i】=0的时候,会停止,总计在0之前有255个数。
![](https://img-blog.csdnimg.cn/direct/251696c952964706b03c3f11efd75428.png)