C语言中整数编码方式(原码、反码、补码)

在 C 语言中,原码、反码、补码的运算规则与其编码特性密切相关,核心差异体现在符号位是否参与运算、进位如何处理以及减法是否能转化为加法等方面。以下是三者的运算规则及特点分析(以 8 位整数为例,符号位为最高位):

一、原码的运算规则

原码是 "符号位 + 数值绝对值" 的直接表示,其运算规则需单独处理符号位,且加法和减法需分开逻辑,灵活性差。

1. 加法运算
  • 若两数符号相同(同正或同负):

符号位不变(仍为 0 或 1),数值位直接相加;若数值位相加后有进位,结果可能溢出(超出表示范围)。

示例:+3(00000011) + +5(00000101)

符号位均为 0,数值位相加:0000101 + 000011 = 0001000,结果为00001000(+8,正确)。

  • 若两数符号不同(一正一负):

需先比较两数数值位的绝对值大小,用 "大绝对值 - 小绝对值",结果的符号取 "绝对值大的数" 的符号。

示例:+5(00000101) + (-3)(10000011)

绝对值 5 > 3,符号取正(0),数值位相减:0000101 - 0000011 = 0000010,结果为00000010(+2,正确)。

2. 减法运算

原码减法需转化为 "被减数 + 减数的相反数",再按加法规则处理(符号相反时的加法逻辑)。

示例:+5(00000101) - (+3)(00000011)

等价于 +5 + (-3),按符号不同的加法规则计算,结果为 + 2(正确)。

原码运算的缺陷
  • 符号位需单独判断,运算逻辑复杂(需比较绝对值、区分加减);
  • 存在两个 0(+0 和 - 0),可能导致运算结果歧义;
  • 实际中几乎不用于计算机运算(仅用于直观表示)。

二、反码的运算规则

反码是原码到补码的过渡编码,其运算规则允许符号位参与运算,但需处理 "循环进位"(最高位进位需回加到最低位),可实现减法转加法,但仍有缺陷。

1. 加法运算
  • 符号位与数值位一起参与加法(按二进制加法规则,逢 2 进 1);
  • 若最高位(符号位)产生进位,需将该进位 "循环" 加到结果的最低位(称为 "循环进位");
  • 运算结果仍为反码,需转换为原码才能得到实际值。

示例 1:+3(反码00000011) + +5(反码00000101)

直接相加:00000011 + 00000101 = 00001000(无进位),结果反码为 00001000,对应原码 + 8(正确)。

示例 2:+5(反码00000101) + (-3)(反码11111100)

相加:00000101 + 11111100 = 100000001(最高位产生进位 1);

循环进位:将进位 1 加到最低位,00000001 + 1 = 00000010;

结果反码为 00000010,对应原码 + 2(正确)。

示例 3:+1(反码00000001) + (-1)(反码11111110)

相加:00000001 + 11111110 = 11111111(无进位);

结果反码为 11111111,对应原码 - 0(存在双 0 问题,不完美)。

2. 减法运算

反码减法可直接转化为 "被减数 + 减数的反码"(因负数的反码是其相反数的反码),再按加法规则处理(含循环进位)。

示例:+5 - (+3) 等价于 +5 + (-3),同上述示例 2,结果正确。

反码运算的缺陷
  • 需处理循环进位,硬件实现稍复杂;
  • 仍存在 - 0(11111111),导致 0 的表示不唯一;
  • 未彻底解决运算问题,仅作为补码的过渡。

三、补码的运算规则

补码是计算机中实际使用的编码,其运算规则最简单:符号位直接参与运算,进位直接丢弃,减法可完美转化为加法,且结果唯一正确。

1. 加法运算
  • 符号位与数值位一起参与加法(按二进制加法规则,逢 2 进 1);
  • 若最高位(符号位)产生进位,直接丢弃该进位(因超出位数的部分不影响结果);
  • 运算结果仍为补码,无需额外处理即可表示正确值。

示例 1:+3(补码00000011) + +5(补码00000101)

相加:00000011 + 00000101 = 00001000(无进位),结果补码为 00001000,对应 + 8(正确)。

示例 2:+5(补码00000101) + (-3)(补码11111101)

相加:00000101 + 11111101 = 100000010(最高位产生进位 1);

丢弃进位:结果为 00000010,对应 + 2(正确)。

示例 3:+1(补码00000001) + (-1)(补码11111111)

相加:00000001 + 11111111 = 100000000(进位 1);

丢弃进位:结果为 00000000(唯一的 0,正确)。

2. 减法运算

补码减法可直接转化为 "被减数 + 减数的补码"(因减去一个数 = 加上它的相反数,而负数的补码是其相反数的补码),再按加法规则处理(进位丢弃)。

公式:a - b = a + (-b)的补码

示例:+5 - (+3) = +5 + (-3)的补码

-3 的补码为 11111101,相加结果同示例 2,得 + 2(正确)。

补码运算的优势
  • 符号位自然参与运算,无需单独判断;
  • 减法完全转化为加法,简化硬件设计(只需加法器);
  • 只有一个 0(00000000),结果无歧义;
  • 进位直接丢弃,逻辑简单,是计算机中整数运算的唯一实现方式。

四、无符号数的运算规则

无符号数(unsigned)没有符号位,其原码、反码、补码完全相同(即二进制数值本身),运算规则为:

  • 加法:按二进制加法,进位直接丢弃(超出位数的部分无效);
  • 减法:按二进制减法,若被减数小于减数,结果为 "模" 减去(减数 - 被减数)(等价于补码运算,因无符号数的补码即自身)。

示例(8 位无符号数):5 - 10

等价于 5 + (256 - 10) = 5 + 246 = 251(因 8 位无符号数的模为 256),结果为 251(正确,无符号数减法的 "借位" 通过模运算处理)。

总结

|----|------------------|---------------------|-------------------|
| 编码 | 加法规则 | 减法规则 | 核心特点 |
| 原码 | 符号位单独处理,异号需比较绝对值 | 转化为 "被减数 + 相反数",同加法 | 逻辑复杂,有双 0,几乎不用 |
| 反码 | 符号位参与运算,进位循环到最低位 | 转化为 "被减数 + 减数的反码" | 需循环进位,仍有 - 0,过渡编码 |
| 补码 | 符号位参与运算,进位直接丢弃 | 转化为 "被减数 + 减数的补码" | 逻辑简单,无歧义,计算机实际使用 |

补码的运算规则是 C 语言中整数存储和运算的基础,理解其规则可解释负数运算、溢出(如int a = 127 + 1结果为 - 128)等现象。

相关推荐
lifallen1 小时前
Flink Exactly Once 和 幂等
java·大数据·数据结构·数据库·分布式·flink
j_xxx404_2 小时前
c语言:字符函数和字符串函数
c语言·开发语言
apocelipes3 小时前
C23和C++26的#embed嵌入资源指南
c语言·c++·开发工具和环境·c23·c++26
liweiweili1264 小时前
GPT和MBR分区
c语言
菜鸟12号5 小时前
详解Linux下多进程与多线程通信(一)
linux·c语言·嵌入式·进程与线程
学不动CV了5 小时前
深入理解C语言内存空间、函数指针(三)(重点是函数指针)
c语言·arm开发·数据库·stm32·单片机·嵌入式硬件·c#
2301_781143567 小时前
江协科技STM32入门教程——通信接口
c语言·嵌入式
不二青衣7 小时前
牛客网50题
数据结构·c++·算法
学不动CV了13 小时前
C语言32个关键字
c语言·开发语言·arm开发·单片机·算法