原码

计算机中所有的数字都是使用 01 这样的二进制数来进行表示的。

这时如果要存储一个数据,比如十进制的 3,那么就需要使用 2 个二进制位来保存,二进制格式为 11,占用两个位置,称为 2 bit 位。

一般占用 8 个 bit 位表示一个字节(B)2 个字节等于 1 个字,所以一个字表示 16 个 bit 位

数字的直接二进制表示称为原码

虽然原码表示简单,但是原码在做加减法的时候,就会出现问题。

以 8 bit 位为例:

  1 + (-1)
取原码:
0000 0001
+
1000 0001
=
0000 1010
取十进制:
-2

显然结果应该为 0-2 的结果是错误的。

为了解决这一问题,引入了反码

反码

正数的反码是其本身。

负数的反码是其原码符号位不变,其余各位取反。

经过上面的定义,再来进行加减法:

  1 + (-1)
原码:
0000 0001
+
1000 0001
反码:
0000 0001
+
1111 1110
=
1111 1111
逆反码(取反):
1000 0000
十进制:
-0

这样虽然结果看起来对了。

但如果 1111 1111 代表 -00000 0000 代表 +0

+0-0 都等于 0

一个 0 用两个二进制数表示,既浪费也不合理,所以又引入了补码

补码

正数的补码就是其本身

负数的补码是其原码符号位不变,其余各位取反(得到反码),最后 + 1

再来看上面的运算:

  1 + (-1)
原码:
0000 0001
+
1000 0001
反码:
0000 0001
+
1111 1110
补码:
0000 0001
+
1111 1111
=
1 0000 0000
省略高位:
0000 0000
逆补码(本身):
0000 0000
逆反码(本身):
0000 0000
十进制:
0

这样就得到了预期的 0

可以看出,补码是计算机数字存储和运算的完美解决方案,所以计算机中的数字都是以补码存储

C 语言使用的也是补码。

取值范围

按照上面原码的定义,可以根据位数推出取值范围。

比如现在一共有 8 bit 位来保存数据,为了表示正负,可以让第一个 bit 位专门来保存符号,这样能够表示的数据范围就是:

  • 最小:1111 1111 => -127
  • 最大:0111 1111 => 127

这里就有个疑问了,我们熟知的 char 占一个字节,也就是 8 bit 位,但它的取值范围是 -128 ~ 127

-128 是从何而来呢?

计算机中的数字都是以补码存储,则:

  -128
二进制:
1 1000 0000
逆补码(-1):
1 0111 1111
逆反码(取反):
1 1000 0000
十进制:
-128

可以看出,补码 -128 的原码也是 -128

由于是用 8 bit 位存储数据,1 1000 0000 所以应该舍弃最高位的 1

由此得到 1000 0000

按照惯性思维,1000 0000 应该为 -0

但前面说了,有了 0 不需要 -0

所以就用 1000 0000 表示 -128

这样运算也是不影响结果的:

  1 + (-128)
原码:
0000 0001
+
1000 0000
=
1000 0001
逆补码(-1):
1000 0000
逆反码(取反):
1111 1111
十进制:
-127

再来看看代码的运行结果:

#include <stdio.h>

int main() {
char c = -128;
printf("%d", c);
}
-128
#include <stdio.h>

int main() {
char c = -128;
printf("%d", c + 1);
}
-127

由此可以看出计算机正是这样运算的。

C语言 03 原码 反码 补码的更多相关文章

  1. 「C语言」原码反码补码与位运算

    尽管能查到各种文献,亲自归纳出自己的体系还是更能加深对该知识的理解.     本篇文章便是在结合百度百科有关原码.反码.补码和位运算的介绍并深度借鉴了张子秋和Liquor相关文章后整理而出.   目录 ...

  2. C语言原码反码补码与位运算.

      目录:     一.机器数和真值     二.原码,反码和补码的基础概念     三.为什么要使用原码,反码和补码     四.原码,补码,反码再深入     五.数据溢出测试     六.位运算 ...

  3. C语言学习笔记之原码反码补码

    原码:就是我们自己看的,以及机器输出给我们看的 补码:机器永远是以补码的形式将数据保存在计算机中 正数: 原码=反码=补码 负数: 反码:原码的符号位不变,其他位取反 ,1变0   0变1 补码:机器 ...

  4. Java 原码 反码 补码

    本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ...

  5. JAVA:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题(5)

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  6. 原码 & 反码 & 补码 & 详解

    本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ...

  7. Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  8. python之计算机硬件基本认知_数据单位_进制间转换_数的原码反码补码

    一:计算机硬件基本认知 cpu:   中央处理器.   相当于人的大脑.运算中心,控制中心. 内存:  临时存储数据. 优点:读取速度快,缺点:容量小,造价高,断电即消失. 硬盘:  长期存储数据. ...

  9. C 标识符, 数据存储形式(原码,反码,补码)

    一.  标识符 第一个字母必须是英文字母或下划线 二. 数据存储形式(补码存储) 最高位是符号位 ---- 0表示整数 ; 1 表示负数 1. 正数:原码 = 反码 = 补码 例子 : (10) 原码 ...

  10. java基础知识-原码,反码,补码

    1.正数:原码,反码,补码:都一样. 2.负数:和正数的储存方式不同,负数都是以补码形式存储的. <1>负数的补码 把负数的原码除了符号位取反后再+1. <2>负数的原码 把对 ...

随机推荐

  1. 在ABP的模块解决方案中使用BootstrapBlazor

    1.为Study.Trade.Blazor.Server.Host引入两个包 成功后效果如下: 2.修改Study.Trade.Blazor.Server.Host的Pages目录下的_Host.cs ...

  2. docker知识整理(备份)

    概念: 镜像:Docker 镜像类似于虚拟机镜像,可以将它理解为一个只读的模板 .镜像是创建 Docker 容器的基础.通过版本管理和增量的文件系统, Docker 提供了一套十分简单的机制来创建和更 ...

  3. PHP项目&RCE安全&调试&追踪&代码执行&命令执行

    常见漏洞关键字 SQL注入:select.insert.update.mysql_query.mysqli等 文件上传:$_FILES.type="file".上传.move_up ...

  4. Java 四种不同的权限修饰

    private 私有属性 只在同一个包下 同一个类中可以调用 同一个包下,不同的类中,可以调用 缺省,保护(protected),公共(public)可以调用, 不同的包下的类中,继承关系,可以调用 ...

  5. 【技术积累】Java 8 新特性

    一.Lambda表达式 Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风格,使J ...

  6. iView 表单验证 如果prop字段和表单里的字段对不上,会触发校验,提示错误信息

    iView 表单验证 如果prop字段和表单里的字段对不上,会触发校验,提示错误信息 原因: 在某些情况,没有id,只有文本的时候,需要返显文本,直接用input显示文本,就会出现,触发数据校验的问题 ...

  7. linux c 打印时间最简单的实例

    最简单的代码,能够解决最棘手的问题,才是解决工程师的需要: #include <stdio.h> #include <time.h> #include <unistd.h ...

  8. Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别

    有个需要是需要在安装包安装初始化时安装 Microsoft Visual c++ 2013 Redistributable 也就是判断软件安装前需不需要运行 vcredist_x64.exe 和 VC ...

  9. day02-SpringMVC映射请求数据

    SpringMVC映射请求数据 1.获取参数值 在开发中,如何获取到 http://xxx/url?参数名1=参数值1&参数名2=参数值2 中的参数? 之前的案例中我们知道:提交的url的参数 ...

  10. day14--Java常用类之字符串相关类02

    Java常用类 2.字符串相关类 String.StringBuilder.StringBuffer类是三个字符串相关类. String类代表不可变字符序列,StringBuilder类和String ...