入门
- 1. 流程控制基本概念
- 2. 流程控制 选择结构
- 3. 流程控制 循环结构
- 4. 四大跳转
- 5. 循环的嵌套
- 6. C 语言图形打印练习
- 7. 函数那点事
- 8. main 函数分析
- 9. 递归函数
- 10. 进制基本概念
- 11. 进制转换
- 12. 原码反码补码
- 13. 位运算符
- 14. 变量内存分析
- 15. Char 类型内存存储细节
- 16. 类型说明符详解
- 17. 数组那点事
- 18. 数组内部存储细节
- 19. 数组注意事项
- 20. 数组和函数
基础
- 1. 计算机常识
- 2. 什么是计算机程序
- 3. 什么是计算机语言
- 4. 常见的计算机语言类型有哪些
- 5. 什么是C语言
- 6. C语言发展历史
- 7. C语言标准
- 8. C语言现状
- 9. 为什么要学习C语言
- 10. 如何学好C语言
- 11. 编写C语言程序用什么工具
- 12. 什么是 QtCreator
- 13. 什么是环境变量
- 14. 如何创建C语言程序
- 15. C语言程序组成
- 16. 函数定义格式
- 17. 如何运行编写好的程序
- 18. C语言程序练习
- 19. 初学者如何避免程序出现 BUG
- 20. 多语言对比
- 21. 注释就是这么简单
- 22. 什么是关键字
- 23. 什么是标识符
- 24. 什么是数据
- 25. C语言数据类型
- 26. 什么是常量
- 27. C语言变量那点事
- 28. printf 函数
- 29. Scanf 函数
- 30. putchar 和 getchar
- 31. C语言运算符大全解
- 32. 阶段练习
进阶
- 1. 计数排序
- 2. 选择排序
- 3. 冒泡排序
- 4. 插入排序
- 5. 希尔排序
- 6. 折半查找
- 8. 二维数组那点事
- 9. 二维数组的遍历和存储
- 10. 二维数组与函数
- 11. 二维数组练习
- 12. 字符串的基本概念
- 13. 字符串常用方法
- 14. 字符串练习
- 15. 指针的基本概念
- 16. 指针变量那点事
- 17. 访问指针所指向的存储空间
- 18. 指针类型与二级指针
- 19. 数组指针的概念及定义
- 20. 指针与字符串
- 21. 指向函数指针
- 22. 结构体详解
- 23. 结构体数组
- 24. 结构体指针
- 25. 结构体内存分析
- 26. 结构体变量占用存储空间大小
- 27. 结构体嵌套定义
- 28. 共用体
- 29. 枚举
- 30. 全局变量和局部变量
- 31. 关键字
- 32. static 与 extern 对函数的作用
- 33. QtCreator 编译过程做了什么
- 34. 计算机运算过程分析
- 35. 预处理指令与宏定义
- 36. 条件编译
- 37. typedef 关键字
- 38. 宏定义与函数以及 typedef 区别
- 39. const 关键字
- 40. 内存管理
- 41. malloc 函数
- 42. free 函数
- 43. calloc 函数
- 44. realloc 函数
- 45. 链表与静态链表
- 46. 动态链表
- 47. 链表销毁与长度计算
- 48. 链表查找与删除
- 49. 文件基本概念
- 50. 文件的打开与关闭
- 51. 读写结构体
- 52. 文件操作函数
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
12. 原码反码补码
原码反码补码
计算机只能识别0和1, 所以计算机中存储的数据都是以0和1的形式存储的
数据在计算机内部是以补码的形式储存的, 所有数据的运算都是以补码进行的
正数的原码、反码和补码
- 正数的原码、反码和补码都是它的二进制
- 例如: 12的原码、反码和补码分别为
0000 0000 0000 0000 0000 0000 0000 1100
0000 0000 0000 0000 0000 0000 0000 1100
0000 0000 0000 0000 0000 0000 0000 1100
负数的原码、反码和补码
- 二进制的最高位我们称之为符号位, 最高位是0代表是一个正数, 最高位是1代表是一个负数
- 一个负数的原码, 是将该负数的二进制最高位变为1
- 一个负数的反码, 是将该数的原码
除了符号位
以外的其它位取反 - 一个负数的补码, 就是它的反码 + 1
- 例如: -12的原码、反码和补码分别为
0000 0000 0000 0000 0000 0000 0000 1100 // 12二进制 1000 0000 0000 0000 0000 0000 0000 1100 // -12原码 1111 1111 1111 1111 1111 1111 1111 0011 // -12反码 1111 1111 1111 1111 1111 1111 1111 0100 // -12补码
负数的原码、反码和补码逆向转换
- 反码 = 补码-1
- 原码= 反码最高位不变, 其它位取反
1111 1111 1111 1111 1111 1111 1111 0100 // -12补码 1111 1111 1111 1111 1111 1111 1111 0011 // -12反码 1000 0000 0000 0000 0000 0000 0000 1100 // -12原码
为什么要引入反码和补码
在学习本节内容之前,大家必须明白一个东西, 就是计算机只能做加法运算, 不能做减法和乘除法, 所以的减法和乘除法内部都是用加法来实现的
- 例如: 1 - 1, 内部其实就是 1 + (-1);
- 例如: 3 * 3, 内部其实就是 3 + 3 + 3;
- 例如: 9 / 3, 内部其实就是 9 + (-3) + (-3) + (-3);
首先我们先来观察一下,如果只有原码会存储什么问题
- 很明显, 通过我们的观察, 如果只有原码, 1-1的结果不对
// 1 + 1 0000 0000 0000 0000 0000 0000 0000 0001 // 1原码 +0000 0000 0000 0000 0000 0000 0000 0001 // 1原码 --------------------------------------- 0000 0000 0000 0000 0000 0000 0000 0010 == 2 // 1 - 1; 1 + (-1); 0000 0000 0000 0000 0000 0000 0000 0001 // 1原码 +1000 0000 0000 0000 0000 0000 0000 0001 // -1原码 --------------------------------------- 1000 0000 0000 0000 0000 0000 0000 0010 == -2
- 正是因为对于减法来说,如果使用原码结果是不正确的, 所以才引入了反码
- 通过反码计算减法的结果, 得到的也是一个反码;
- 将计算的结果符号位不变其余位取反,就得到了计算结果的原码
- 通过对原码的转换, 很明显我们计算的结果是-0, 符合我们的预期
// 1 - 1; 1 + (-1); 0000 0000 0000 0000 0000 0000 0000 0001 // 1反码 1111 1111 1111 1111 1111 1111 1111 1110 // -1反码 --------------------------------------- 1111 1111 1111 1111 1111 1111 1111 1111 // 计算结果反码 1000 0000 0000 0000 0000 0000 0000 0000 // 计算结果原码 == -0
- 正是因为对于减法来说,如果使用原码结果是不正确的, 所以才引入了反码
- 虽然反码能够满足我们的需求, 但是对于0来说, 前面的负号没有任何意义, 所以才引入了补码
- 由于int只能存储4个字节, 也就是32位数据, 而计算的结果又33位, 所以最高位溢出了,符号位变成了0, 所以最终得到的结果是0
// 1 - 1; 1 + (-1); 0000 0000 0000 0000 0000 0000 0000 0001 // 1补码 1111 1111 1111 1111 1111 1111 1111 1111 // -1补码 --------------------------------------- 10000 0000 0000 0000 0000 0000 0000 0000 // 计算结果补码 0000 0000 0000 0000 0000 0000 0000 0000 // == 0
- 虽然反码能够满足我们的需求, 但是对于0来说, 前面的负号没有任何意义, 所以才引入了补码
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论