【C语言进阶篇】整数在内存的存储——原码、反码、补码

简介: 【C语言进阶篇】整数在内存的存储——原码、反码、补码

一、原反补的简介

计算机中的整数有三种表示方法,即原码反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同 。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理

1.1 原码

原码是最直接的表示法,它直接将一个数转换成二进制形式,并用最高位作为符号位0代表正数,1代表负数

为了更简单直观的举例说明,下面都以short int类型(16位)来进行演示

正数5的原码表示如下(最高位0表示正数)

00000000 00000101

负数-5的原码表示如下(最高位1表示负数)

10000000 00000101

1.2 反码

反码是原码的一种变形,对于正数,其反码与原码相同对于负数,除符号位外,其余各位取反

正数5的反码与原码相同

00000000 00000101

负数-5的反码,是将原符号位保持为1,其他位取反

11111111 11111010

1.3 补码

正数的补码就是它的原码负数的补码定义为其原码除符号位外所有位取反后再加上1

正数5的补码与原码、反码相同

00000000 00000101

负数-5的补码,在其反码的基础上+1

11111111 11111011

1.4 相互转换

对于正数来说,其原反补是相同的,不需要进行转换

对于负数来说,每一次转换需要进行一次运算

       负数的反码=原码符号位不变,其他位取反(或者通过补码-1得到)

       负数的补码=原码符号位不变,其他位取反再+1(或者通过反码+1得到)

       负数的原码=反码符号位不变,其他位取反(或者通过补码-1得到反码,再将除符号位外其他位取反得到)(还有一种方式是通过对补码先取反(除符号位),再+1也可以得到原码)

二、为什么需要引入三种不同的二进制表示形式

原码

首先,原码就是直接将数值的二进制形式转换为机器码。它简单直观,易于理解。

对于计算机的加减运算却并不适合,因为计算机中的加法和减法操作需要一种方式来处理溢出和符号。采用原码时会出现“零”的问题:正零和负零有各自的表示,这在计算上增加了复杂性。

反码

其次,为了解决原码的这个问题,反码被引入。

反码的符号位与原码相同,但数值部分是原码数值的各位取反(包括符号位)。

在反码表示法中,加法和减法运算可以用相同的方式处理,通过将加法和减法转换为对加数和被加数取反并加一或减一的操作。

使用反码后虽然解决了零的唯一性问题,但加法运算仍有缺陷,因为两个同号的最小值相加可能会溢出到另一个符号区,导致结果错误。

补码

反码仍然存在一个问题,即在处理负数时,最高位(符号位)可能会产生进位,使得无法区分正数和负数。为了解决这个问题,补码被引入。

补码的符号位与原码相同,但数值部分是原码数值的各位取反(不包括符号位),然后加一。

在补码表示法中,加法和减法运算可以统一处理,通过将加法和减法转换为对加数和被加数取反并加一或减一的操作。同时,补码表示法还可以避免符号位的进位问题。

 

三、总结

原码、反码和补码都是为了解决计算机内部数值表示和运算的问题而引入的。

原码是直接将数值的二进制形式转换为机器码;

反码通过将原码数值的各位取反并处理符号位来解决加法和减法运算的问题;

补码通过将反码数值加一来解决符号位进位的问题,并将加法和减法运算统一处理。

最终,补码成为计算机内部数值表示和运算的标准方式。

相关文章
|
1月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
|
30天前
|
存储 监控 Docker
如何限制docker使用的cpu,内存,存储
如何限制docker使用的cpu,内存,存储
|
2月前
|
存储 固态存储 芯片
计算机中内存与存储
【7月更文挑战第28天】
39 1
|
2月前
|
存储 弹性计算 程序员
新手程序员如何阿里云服务器配置?新人开发者CPU内存带宽存储怎么选?
对于新手开发者、个人或学生选择阿里云服务器,推荐ECS经济型e实例(ecs.e-c1m1.large),适用于小型网站或轻量应用。配置2核2G内存、3M固定带宽、40G ESSD系统盘,仅99元/年且续费同价。
|
1月前
|
存储 编译器 C语言
数据在内存中的存储
数据在内存中的存储
|
16天前
|
存储 Serverless C语言
【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数
本文介绍了C语言中的`gets`和`puts`函数,`gets`用于从标准输入读取字符串直至换行符,并自动添加字符串结束标志`\0`。`puts`则用于向标准输出打印字符串并自动换行。此外,文章还详细讲解了`str`系列字符串操作函数,包括统计字符串长度的`strlen`、复制字符串的`strcpy`、比较字符串的`strcmp`以及拼接字符串的`strcat`。通过示例代码展示了这些函数的具体应用及注意事项。
|
19天前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
19天前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。
|
24天前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。
|
24天前
|
C语言
C语言 字符串操作函数
本文档详细介绍了多个常用的字符串操作函数,包括 `strlen`、`strcpy`、`strncpy`、`strcat`、`strncat`、`strcmp`、`strncpy`、`sprintf`、`itoa`、`strchr`、`strspn`、`strcspn`、`strstr` 和 `strtok`。每个函数均提供了语法说明、参数解释、返回值描述及示例代码。此外,还给出了部分函数的自实现版本,帮助读者深入理解其工作原理。通过这些函数,可以轻松地进行字符串长度计算、复制、连接、比较等操作。