补码
补码主要用于解决负数的储存和运算。
以下是一些不正规的理解。
如果一个整数型在内存中只占用n个比特,则第n+1位为1,其余为0(十进制中等于2n),则让这个数(2n)减去想要存储的负数的绝对值,就是这个负数的二进制表示(是它的补码)。
这个负数和它对应的正数之和相加,则变为那个数(2n),但由于该整数型总共只有n个比特,故n+1位会被直接丢掉到,导致相加为0。
这是一种考虑如何存储负数的思路——负数与它对应的正数相加之和为零嘛。
这也就导致一个问题,比如char整数类型,11111111作为补码到底理解为-1还是255?
由思路我们可以知道,我们有char整数类型,共8个比特的占用,如果只表示正数,则最大只能表达11111111,即0到255之间的数,共有256个数。我们现在还希望它来存储负数,并且思路是
1+(-1)=0 2+(-2)=0 … 也就是说我们其实是把256个数掰开来用,1,-1;2,-2…这样一对一对
因此总共有128对,最大是-128和128,最小是0和-0;
0和-0是一回事儿但是128和-128不是一回事情,128与-128都是10000000,不过规定100000000是-128。
char数据类型
ASCII码中利用八个bite,从0d(0000 0000b)到127d(0111 1111b),每个二进制数均对应一个特定的字符。char数据类型能有效接收这128个字符。但不论传给什么数据类型,字符也好数值也罢,其最终都以二进制数保存。比如定义变量c是char数据类型,不论赋给c的是数值49还是字符’1’,它们在内存中均是以00110001来存储的。
当输出要求中要求%c,则编译器理解为要把存储的二进制码转换为对应的字符输出。而如果输出要求为%d,编译器理解为把二进制数转换为十进制数输出。
- 由于char数据类型只接受一个字节的长度。因而如果传入的数据大于255d(1111 1111b),则超出第八位的溢出部分会直接丢失。比如821d(0011 0011 0101b),存储时只会保留后八个比特,因而实际上存储为( 0011 0101b),对应十进制为53d,最终会输出53。
- 由于补码的规则,当传入的数或者经过溢出丢失处理后的数不存在溢出问题(小于255d),但大于127d对应二进制(1000 0000b),会被当做补码处理,最终输出会是负数。
C中scanf(“%c”,&c)的意思是取一个字符并将它赋值给c。如果这里输入1,则会因为%c而被强行转换为字符’1’,然后用其对应的二进制码(0011 0001b)存储,当要求以%d输出时,结果会是 49。