#include <stdio.h>
int main()
{
short c = '\xFE';
int a = 0xFE;
char b = 389;
printf("%d %d", c, b);
}
要弄明白上面这段代码,首先要知道:在计算机的数据存储中,不管是正数还是负数都是以补码的形式储存的。
计算机中的数据存储
要弄明白补码是怎么来的,就要知道原码、反码。
原码
原码形式很简单,就是将给的这个数展开为2进制,然后根据他的数据类型在不足的位置补0。
其中 int 类型是占4个字节32位,short类型站2个字节 16位,char类型占1个字节8位。
例如下表:
变量定义(正数) | 2进制展开 |
int a = 7 | 0000 0000 0000 0000 0000 0000 0000 01111 |
char a = 7 | 0000 0111 |
short a = 7 | 0000 0000 0000 0111 |
变量定义(负数) | 2进制展开 |
int a = -7 | 1000 0000 0000 0000 0000 0000 0000 0111 |
char a = -7 | 1000 0111 |
short a = -7 | 1000 0000 0000 0111 |
其中,2进制展开的最左边一位(最高位)也就是符号位,正数最高位为0,负数最高位为1。
反码
正数的反码是原码本身,负数的反码是除去最高位符号位,其它位0 变 1,1 变 0。
变量 | 反码形式 |
int a = 7 | 0000 0000 0000 0000 0000 0000 0000 0111 |
short a = -7 | 1111 1111 1111 1000 |
char a = -7 | 1111 1000 |
补码
正数的补码是原码本身,负数的补码是在它本身反码的基础上+1。
变量 | 补码形式 |
int a = 7 | 0000 0000 0000 0000 0000 0000 0000 0111 |
short a = -7 | 1111 1111 1111 1001 |
char a = -7 | 1111 1001 |
结论
总结为以下:
正数的补码就是本身自己的原码。负数的补码=自己原码取反+1=反码+1
题目讲解
现在知道了数据在计算机中都是以补码的形式存在的。
#include <stdio.h>
#include <stdio.h>
int main()
{
short c = '\xFE';
int a = 0xFE;
char b = 389;
printf("%d %d", c, b);
}
short c='\xFE';
题目之中 short c = '\xFE','\xFE'是什么?注意,它外面有单引号,就像'a'、'B'一样,'\xFE'整体是一个字符(char类型),而'\xFE'这种表示是一种16进制输入,用前缀:\x来表示16进制不同于0x,前者表示16进制整体必须带' '双单引号,0x则不用。
FE的展开是1111 1110,上面提到了char类型的长度是一个字节(8位),则它的最高位为1,表示这个数被char类型接入的时候是一个负数,负数在计算机中的储存方式上面提到了,现在要做的就是将其表示为补码形式,1111 1110>1000 0001(反码)>1000 0010(补码),而它最终就表示为了看到的运行框中的-2。
上面说了'\xFE'首次被计算机接收并处理为了-2,也就是8位1000 0010(因为char类型只有8位),接受它的参数是short c,shot是2个字节,16位,当把char类型表示给short类型的参数时,之后输出结果中仍然是-2,因为接受的参数为16位,大于后面的char类型,所以计算机这时候在处理的时候,只会在不足16位的地方补0,即0000 0000 1000 0010。这个值就是'\xFE'最终在计算机中的表示方式。
char b=389;
首先,在不考虑前方接受参数类型的情况下,389的二进制展开形式是1 1000 0101,这个时候,因为它的长度是9位,而char类型是8位,所以最高位的1会被“吞掉”,只剩下1000 0101,由于最高位是1,负数,它的补码表示形式是1111 1100,不看最高位符号位,它所表示的数是123,最终计算机存储的所表示出来就是-123。
int a=0xFE;
这钟情况下,后面的0xFE就相当于一个数,就比如平常见到的int a=5之类的,由于有符号int类型的范围是2^(-31)~2^31-1;只要这个输入的数不超过这个范围,输出的数就不会发生变化,若大于这个范围,还是和上述一样,“吞掉”多余位+补码表示。
最终运行结果在devc++。希望对大家有帮助。