翁恺 6-

计算机只会做加法 ,不会做减法。比如要算 0-1(其实就是 -1),或者算 -1+1=0,计算机得把 "减法" 变成 "加法" 来算 ------补码就是干这个的:把负数转换成一个 "正数",让它和原数相加后,结果刚好是 "满位溢出",溢出后剩下的就是 0。

第一步:先看正数的 8 位二进制

例子里的数都是 8 位(比如 0 是00000000,1 是00000001):

  • 0 的 8 位二进制:00000000
  • 1 的 8 位二进制:00000001

第二步:解决 "-1+1=0" 的问题

我们希望计算机算 -1 + 1 能得到 0,但计算机只会加,那 -1 得变成啥数,和00000001相加后能等于 0?

看例子里的算式:11111111 + 00000001 = 100000000

注意:8 位二进制只能存 8 个数 ,所以100000000里的第 9 位(最前面的 1)会被 "丢掉",剩下的后 8 位就是00000000(也就是 0)。

刚好!11111111 + 00000001 溢出后等于 0,所以我们就把 11111111 规定为 -1 的补码。

第三步:验证 "0-1=-1"

例子里说 "因为 0-1→-1,所以 - 1=00000000 - 00000001"。

但二进制里00000000减00000001不够减,得借位 (相当于借一个 "8 位满值"):00000000 借位后变成 100000000(相当于十进制的 256),然后减00000001:100000000 - 00000001 = 11111111

所以 -1 的补码就是 11111111(和第二步的结果一致)。

第四步:补码的通用规则

对于 8 位二进制(n=8),一个负数-a的补码 = 2^8 - a(因为 2^8=256,是 8 位二进制能存的 "满值"):

  • 比如-1的补码 = 256-1=255,255 的 8 位二进制就是11111111;
  • 再比如-2的补码 = 256-2=254,对应的 8 位二进制是11111110

二进制串本身没有 "固定身份"------ 它既不是天生的 "补码",也不是天生的 "十进制"。就像一串字符 "12",可以是数字 "十二",也可以是月份 "十二月",全看我们用什么规则去理解

同一串二进制,规则不同,解读出的数字就不同

这里的 8 位二进制是按 ** 补码(有符号数)** 解读的 ------ 补码规则是:

  • 第 1 位(最高位)是符号位 :0表示正数 / 0,1表示负数;
  • 剩下的 7 位是数值位,用来表示具体大小。

第二步:拆分 8 位二进制的 3 类情况

一个字节有 8 位,所有可能的二进制组合是 00000000 ~ 11111111(共 256 种),这些组合对应 3 类数值:

1. 单独的 0:00000000 → 对应十进制0

最高位是 0(符号位为正),数值位全是 0,所以直接是 0。

2. 正数范围:00000001 ~ 01111111 → 对应十进制1 ~ 127
  • 符号位是 0(表示正数),剩下 7 位是数值位;
  • 数值位最小是0000001(对应 1),最大是1111111(计算:\(2^6+2^5+...+2^0=64+32+16+8+4+2+1=127\));
  • 所以正数能表示1~127。
3. 负数范围:10000000 ~ 11111111 → 对应十进制-128 ~ -1
  • 符号位是 1(表示负数),剩下 7 位是补码的 "数值部分";
  • 补码负数转十进制的规则是:\(- (2^8 - 二进制对应的无符号数)\)(2^8 是 8 位的 "满值"=256)。

举两个关键例子:

  • 最大的负数(最接近 0):11111111 → 无符号数是 255 → \(- (256-255) = -1\);
  • 最小的负数:10000000 → 无符号数是 128 → \(- (256-128) = -128\);

所以负数能表示-128 ~ -1。

第三步:总结

1 个字节(8 位补码)能表示的所有数值是:-128 ~ 0 ~ 127(共 256 个数,刚好对应00000000 ~ 11111111的 256 种二进制组合)

  • char 类型 :在绝大多数电脑里,char 只占 1 个字节(8 位二进制),就像一个 "小盒子",最多只能装 8 个 0 或 1;
  • int 类型 :通常占 4 个字节(32 位二进制),是一个 "大盒子",能装 32 个 0 或 1。

255 转换成二进制是 11111111(8 个 1),刚好填满 1 个字节。

对于 char c = 255;:

char 是 "1 字节的有符号类型"------ 它的规则是:

  • 只用 8 位存数据;
  • 最高位(第 1 位)是 "符号位":0表示正数,1表示负数;
  • 超出范围(char 能表示的范围是 -128 ~ 127)会 "溢出",按补码规则解读。

255 的 8 位二进制是 11111111:

  • 最高位是 1(符号位为负);
  • 按补码规则(之前讲过的),11111111 表示 -1(因为 11111111 作为 8 位补码,对应十进制 - 1);
  • 所以 c 输出 -1。
对于 int i = 255;:

int 是 "4 字节的有符号类型"------ 它的规则是:

  • 用 32 位存数据,255 的 32 位二进制是 00000000 00000000 00000000 11111111(前面补 24 个 0,凑满 32 位);
  • 最高位是 0(符号位为正),所以直接按正数解读,就是 255;
  • 所以 i 输出 255。

运行这段代码,会打印:c=-1, i=255

同样的数值 255,因为存在不同大小的 "盒子"(char和int)里,且 "解读规则" 不同:

  • 小盒子(char)装不下 255,按补码规则变成了 - 1;
  • 大盒子(int)装得下,直接按正数解读为 255

unsigned 是 C 里的一个 "规则开关"------ 它的作用是告诉计算机:"这个变量里的二进制,没有正负,全是正数"。

举个之前的例子:

  • 普通 char(默认 "有符号"):8 位二进制 11111111 会被解读成 -1(因为最高位是符号位);
  • 加 unsigned 变成 unsigned char:同样的 11111111 会被解读成 255(因为没有符号位,全是数值位)。

二、图里的 "字面量加 u/U" 是啥意思?

"字面量" 就是你直接写的数字(比如 255),加 u 或 U(比如 255U)是告诉计算机:"这个数字是无符号的,别把它当成负数"。

比如写 unsigned int a = 255U; ------ 这里的 255U 明确说 "我是无符号数",和 unsigned int 的规则对应上。

三、那两个 "圈图" 是啥意思?

这两个圈是 **"二进制存满了会'绕圈'"** 的示意图(因为变量的存储空间是固定的,存不下就会溢出):

第一个圈:有符号数(不带 unsigned,比如普通 char)
  • 范围是 -128 ~ 127(8 位有符号数的范围);
  • 圈是 "循环的":比如 127 再加 1,存不下了,就会 "绕到" -128;-128 再减 1,会 "绕到" 127。
  • 图里的箭头就是这个 "绕圈" 的过程(比如从 127 转到 -128,从 0 转到 -1)。
第二个圈:无符号数(带 unsigned,比如 unsigned char)
  • 范围是 0 ~ 255(8 位无符号数的范围);
  • 圈也是循环的:比如 255 再加 1,存不下了,会 "绕到" 0;0 再减 1,会 "绕到" 255。
  • 图里的箭头就是这个过程(比如从 255 转到 0)

不管是 10 进制、8 进制还是 16 进制的数字,计算机内部只会用 "二进制" 来存储

8 进制、16 进制是 ** 人类为了 "简化二进制的书写"** 搞出来的 "字符串写法"------ 因为二进制太长了,8/16 进制是给人看的、简化的字符串写法

e是科学计数

输出

左边是对的,因为浮点只有七位有效,这里输出10位

所以比如算钱的时候,不能用小数点误差会累积,需要换成整数

1个比特表达负数,11表达指数,后面的表示分数多少

相关推荐
番茄灭世神3 分钟前
PN学堂GD32教程第12篇——SPI与Nor Flash
c语言·stm32·单片机·嵌入式·gd32·总线协议
苏辰澈44 分钟前
C++独属于自己的变身:多态
c语言·开发语言·c++·visualstudio·编辑器
水饺编程1 小时前
第1章,[Win32 章节]:在 VS2019 里面安装 MSDN
c语言·c++·windows·visual studio
水饺编程1 小时前
第1章,[Win32 章节]:编程环境与 MSDN
c语言·c++·windows·visual studio
wuminyu12 小时前
ForkJoinPool窃取线程在扫描其他WorkQueue时的随机采样算法与Phase线程挂起唤醒机制解析
java·linux·c语言·jvm·c++
Logic10112 小时前
C语言/数据结构欧几里得算法题解:长方形切割最大正方形——贪心划分计数
c语言·数据结构·算法·贪心算法·时间复杂度·空间复杂度·欧几里得算法
老王爱玩车14 小时前
文件操作从打开到缓冲区
c语言·开发语言·学习
Zwawa16 小时前
传感器模块都在交出什么:从模拟电压到数字协议
c语言·单片机·嵌入式
程序员zgh17 小时前
C++ erase() 函数用法
c语言·开发语言·c++·学习
迪丽热爱17 小时前
一、C语言概述与程序结构
c语言·开发语言·算法