匿名用户
1级
2018-05-28 回答
挺有意思的题目。逐条解释吧。
首先要明白char是按一个字节存储的,int是按4个字节的存储的,无符号数是和正数的符号位一样。
%x按4个字节打印十六进制(有符号),%d按4个字节打印十进制(有符号)。
第一个打印:要按4个字节的%x格式打印一个字节的char型,所以输出了这么多。
%d输出的第二个:要以有符号的格式%d输出一个无符号的数ic,所以会输出负数。
%d输出的第三个:要以有符号而且是4字节的格式%d输出一个无符号而且是一个字节的char型,所以得到224。
追问:
是的,谢谢参与
追答:
%x不分符号,是我写错了。
汗,写的很抽象,但收到一个赞成,看来有人看懂了!解释一下吧:
signed char sc = 0xe0;内存也保存为0xe0。
unsigned int ic = sc;这一句,把有符号的字符型赋给无符号的整型。计算机的操作是,先把sc扩充成四字节,有符号数扩充的方法是按照符号位来填满空缺部分,于是ic就变成了0xffff ffe0;然后有符号数变成无符号数,在内存中没变化,还是0xffff ffe0。
unsigned char uc = sc;这一句,把有符号字符型赋给无符号字符型。计算机的操作是,把内存中的sc值直接copy给uc,所以uc在内存中和sc一样,都是0xe0。
看%x的第一个打印,把0xe0扩充成四字节,有符号数扩充的方法是按照符号位来填满空缺部分,所以输出ffff ffe0。第二个打印,直接输出,没得说的。第三个打印,无符号数扩充,前面说了,无符号数看作和正数的符号位一样。全部用0填充,所以就是0x0000 00e0,0不打印,打印e0。
%d的输出和%x的值一样,只是形式不一样,不解释。
分析0xe0对应的十进制数:
因为0xe0的二进制是1110 0000,所以计算机存储的就是1110 0000,是按反码存储。首位是符号位,为1表示负数。因为负数的反码是对应原码按位取反再加1,那倒推,原码就是反码减1再按位取反。
好,首位的1先不管,110 0000减一得101 1111;按位取反得原码010 0000,而这个数的十进制就是32。所以对于有符号字符型,0xe0就是-32。
追问:
你上边的嗯,基本是这样,我懂。我现在不明白的是,printf %d输出,你说是4字节
那么这个函数的形参应该也是4字节,
%d输出第一个sc 应该也是扩充吧 负数扩充 0xFFFF FFE0
%d输出第二个ic 不需要扩充 0xFFFF FFE0
%d输出第三个个uc 正数,需要扩充 0x0000 00E0
问题就是:
怎么 0xFFFF FFE0有符号打印,是-32呢?
-32应该是0XE0啊
追答:
1111 1111 1111 1111 1111 1111 1110 0000 --- 0xffff ffe0
1111 1111 1111 1111 1111 1111 1101 1111 --- 减1
0000 0000 0000 0000 0000 0000 0010 0000 --- 取反得原码,这就是他妈的32
够清楚了没有
追问:
明白了。我知道我纠结的问题所在了。那个,你说的反码,应该叫做补码
反码只是取反,负数和正数都是按补码存储的
追答:
啊,不好意思,混淆名词了