最近小编在写C 编码转换的问题,都快被弄疯来,看来很多资料感觉自己在计算机变成底层这一块不是很熟练,所以恶补来一下,这边总结出来给大家分享。

大家都知道计算机只认识0和1,但是0和1对人又不友好,怎么做到这两者的转换呢?这就需要从计算机的存储讲起。

c语言补码转原码(C手撕底层位)(1)

位和字节

位:来自英文bit,音译为“比特”,表示二进制位。位是计算机内部数据储存的最小单位,11010100是一个8位二进制数。

字节:来自英文Byte,音译为“拜特”,习惯上用大写的“B”表示。字节是计算机中数据处理的基本单位。计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。八位二进制数最小为00000000,最大为11111111;通常1个字节可以存入一个ASCII码,2个字节可以存放一个汉字国标码。

unsigned int、signed int和unsinged char 、signed char

一般来说char类型变量在计算机内存里占用1个字节,也就是8个比特(byte),unsinged就是无符号的意思,signed就是有符号的意思。char默认是unsinged类型

c语言补码转原码(C手撕底层位)(2)

char

如果是unsinged char那么最高位(最左边)就可以用来表示数字,那么char能表示的范围是二进制的00000000~11111111,转换为十进制就是0~255。

如果是signed char那么最高位(最左边)就需要用来表示正负0为正,1为负,那么只有剩余7位能表示数字,所以能表示的范围就是1111 1111~01111111 ,转换位十进制就是 - 127~ 127。还有一个 1000 0000 用它来表示 -128,因为没有负0的概念。计算机里负数都是用补码来表示。关于补码的概念后面会讲。

unsigned int和signed int在char的基础上理解,只不过int是四个字节,也就是4*8=32位。int默认是signed有符号位的。所以,unsigned int表示的范围是:0~2的32次方-1。signed int表示的范围是:-2的31次方~2的31次方-1。

c语言补码转原码(C手撕底层位)(3)

int

原码、反码、补码

要了解清楚原码、反码、补码需要先了解两个额外的概念:机器数和真值

机器数:一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的比如,十进制中的数 3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。这里的 00000011 和 10000011 就是机器数。

真值:拿上面的机器数00000011(十进制 3)来讲,其形式值131(又二进制转10进制得来),但是实际我们要的是 3,所以我们需要去掉最高位符号位:0000 0001的真值 = 000 0011 = 3,1000 0001的真值 = –000 0011 = –3。

好,了解来上面两个概念,我们就可以来看原码、反码、补码了

原码:顾名思义,原码就是我原来要表示的值的二进制码,所以 3/-3的原码是需要考虑符号位的: 3的原码是:0000 0011。-3的原码是:1000 0011。

反码:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反

3 原码是:0000 0011 反码是:0000 0011

-3 原码是:1000 0011 反码是:1111 1100

补码:

正数的补码就是其本身

即在反码的基础上 1

3 原码是:0000 0011 反码是:0000 0011 补码是:0000 0011

-3 原码是:1000 0011 反码是:1111 1100 补码是:1111 1101

为什么要存在这么多码

看完上面的内容,大家一定很懵,为什么要弄这么多码。这是因为计算机是不辨别"符号位",因为这显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法。我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。

在加减乘除中,正数当然很好处理,如果遇到负数就会有问题,我们来看一下3-3如果用原码运算会怎么样:

3-3在计算机中只有加法,所以3-3=3 (-3);

0000 0011 1000 0011=10000110,我们算上符号转为十进制是:-6;

既然原码不行,那用反码?好,试一下看看

0000 0011 1111 1100 = 111111111,我们算上符号转为十进制是:-127;

那再试试补码

0000 0011 1111 1101 = 00000000;我们算上符号转为十进制是:0;

OK,是对的;

所以计算机存数值都是存补码。至于补码背后的数学原理,这里超出了编程范围,主要是小编也不太懂啊!大家有兴趣的可以去查一查。好像是什么同余原理。

END

纯手KEY,希望大家多多支持小编,点个关注~~~

,