整数在内存中的存储:原码、反码、补码 大小端字节序

news2024/9/21 17:33:46

在这里插入图片描述

本篇博客会讲解整数在内存中的存储形式,以及整数二进制的3种表示形式:原码、反码、补码,还有大小端的相关知识点。相信读完本篇博客,大家对内存的了解会上一个台阶。

注意:本篇博客讨论的是整数在内存中的存储,像char, short, int, long, long long的有符号和无符号类型存储的都是整数。

认识原码、反码、补码

对于整数,有原码、反码、补码之分,它们都是整数的二进制的表示形式。有符号整数的计算方式如下:

  1. 正整数的原码、反码、补码相同,都是整数直接转换成二进制的结果。
  2. 负整数的原码是把该数转换成二进制的结果,反码和补码需要通过原码计算出来。
  3. 负整数的反码的计算规则:原码的符号位不变,其他位按位取反得到反码。
  4. 负整数的补码的计算规则:反码+1得到补码。

下面来举2个例子,分别表示正整数和负整数。

正整数以10为例子:10作为十进制数,直接转换成二进制,得到的就是它的原码。又因为10是正整数,故原码、反码、补码相同。所以问题呢就转换成如何把十进制的10转换成二进制。

把十进制的10转换成二进制,得到的是1010。这是怎么来的呢?对于二进制的1010,从右往左数,最右边的0代表0×20,倒数第二位的1代表1×21,倒数第三位的0代表0×22,最左边的1代表1×23,所以二进制的1010就代表十进制的1×23+0×22+1×21+0×20=8+0+2+0=10。

严谨点来说:10的默认类型是int,一个int大小是4个字节,也就是32个bit位,应该填满32位,不够在高位补0,所以10的原码、反码、补码都是:00000000000000000000000000001010

再举个负数的例子:-10的原码、反码、补码是多少?对于负数,是“有符号数”,最高位表示符号位,用1表示负数,其余的位和10的二进制相同:10000000000000000000000000001010。这就是-10的原码。

-10作为一个负数,反码和补码需要通过原码来计算。反码的计算规则是,原码符号位不变,其他位按位取反,也就是说,最高位的1表示符号位,不变,其余位1变0,0变1。反码就是:11111111111111111111111111110101

补码的计算规则是:反码+1即是补码,所以-10的补码是:11111111111111111111111111110110

整数在内存中是以哪种形式存储的呢?事实上,整数在内存中存储的是二进制的补码,这一点是可以验证的,但是同时涉及到大小端的问题。

大小端字节序

大小端字节序,简称大小端,指的是,以字节为单位,内存中的数据是如何存储的。分为2种存储方式,分别是大端字节序和小端字节序,简称大端和小端。

  1. 大端字节序:把高位字节处的数据存储在低地址处,把低位字节处的数据存储在高地址处。
  2. 小端字节序:把高位字节处的数据存储在高地址处,把低位字节处的数据存储在低地址处。

这是什么意思呢?我在VS2022环境下验证一下:根据前面所讲,整数在内存中存储的是补码,我们来观察一下-10在内存中是如何存储的。

在这里插入图片描述
观察到,当左边是低地址,右边是高地址,即地址从左到右是由低到高变化的,此时内存中存储的是0x f6 ff ff ff。这是什么意思呢?

整数在内存中是以二进制的补码的形式存储的。前面计算过了,-10的补码是:11111111111111111111111111110110。下面我们把它转换成十六进制。

先4个为一组分开:1111 1111 1111 1111 1111 1111 1111 0110

然后分别转换每一组,其中1111是f,0110是6:0x fffffff6。一个十六进制位是4个bit位,2个十六进制位就是一个字节,把这个数以字节为单位分隔开,就是:0x ff ff ff f6

而内存中存储的却是:0x f6 ff ff ff,这是为什么呢?在VS环境下观察内存,从左到右,地址是由低到高变化的,也就是说,本来-10补码中的高位的ff存储在了高地址处,而-10补码中的低位的f6存放在低地址处,这就是“小端字节序”的存储方式,看起来像是数据“倒着放”。

整数在内存中的存储

整数在内存中的存储,是由以下2点决定的:

  1. 整数在内存中存储的是补码的二进制。
  2. 根据机器是“大端字节序”还是“小端字节序”来决定是“正着放”还是“倒着放”。

以上是数据“如何存”,那如何把一个数据“往外拿”呢?把存的过程倒过来就行了。

  1. 根据大小端字节序,把数据“正着”或者“倒着”拿出来。
  2. 把拿出来的补码转换成原码。

那如何把补码转换成原码呢?原码怎么转换成补码,把这个过程倒过来就行了,以下是如何把补码解析成有符号数的过程。

  1. 若符号位是0,则是正数,此时原码、反码都和补码相同。若符号位是1,则是负数,需要计算反码和原码。
  2. 补码-1得到反码。
  3. 反码的符号位不变,其他位按位取反得到原码。

注意:如果要解析成无符号数,最高位就不是符号位了,而是数据的一部分,此时一律看做正整数来处理。

举个例子,前面我们观察到小端机器下-10在内存中存储的是:0x f6 ff ff ff,由于小端是“倒着存”的,所以先正过来:0x ff ff ff f6,再转换成二进制:1111 1111 1111 1111 1111 1111 1111 0110,即11111111111111111111111111110110,这就是补码,由于符号位(最高位)是1,是一个负数,需要根据补码计算反码和原码。先把补码-1,得到反码:11111111111111111111111111110101,把反码符号位不变,其他位按位取反得到原码:10000000000000000000000000001010,再转换成十进制,就得到了-10。

为什么要存补码?

整数在内存中存储的是补码的二进制,这主要有2个优点。

先说第一个优点:使用补码来存储,统一了符号位和数值位。换句话说,符号位和数值为可以统一计算。在CPU中,只有加法器,所有的计算都要转换成加法。比如,计算1-1,先要转换成计算1+(-1),然后写出1和-1的补码:

1作为正数,原码、反码、补码相同,都是:00000000000000000000000000000001

-1作为负数,原码是:10000000000000000000000000000001,原码符号位不变,其他位按位取反后得到反码:11111111111111111111111111111110,反码+1得到补码:11111111111111111111111111111111

接下来计算1+(-1),也就是这样计算:

  00000000000000000000000000000001
+ 11111111111111111111111111111111
 100000000000000000000000000000000

由于整数只能存储32个bit为,最高位的1就丢了,只剩下00000000000000000000000000000000,得到的结果就是0。

根据以上的计算,有没有发现,我们根本没有管哪里是符号位,哪里是数值位,就是简单粗暴的把补码写出来,加起来,完事。CPU把内存中存储的补码拿出来,进行加法运算时,根本不用考虑哪里是符号位,那里是数值位,这就做到了把符号位和数值位统一处理。

在说第二个优点之前,还需要了解一个知识点:把补码转换成原码的另一种方式:先把补码的符号位不变,其他位按位取反,再+1,也能得到原码。比如:已知-10的补码:11111111111111111111111111110110,把补码的符号位不变,其他位按位取反得到:10000000000000000000000000001001,再+1得到:10000000000000000000000000001010,这样也得到了-10的原码。

有没有发现,如果用这种方式把补码转原码,那么就和原码转补码的方式相同了,都是“取反再+1”!所以,用补码来存储时,把补码转原码,以及原码转补码可以使用同一套硬件电路,降低了电路的复杂性。

总结

  1. 整数的2进制有3种表示形式,分别是原码、反码、补码。
  2. 正整数的原码、反码、补码相同,负整数的原码、反码、补码需要计算。把整数直接转换成2进制,就是原码。负整数的原码的符号位不变、其他位按位取反得到反码。负整数的反码+1得到补码。
  3. 从补码转原码,需要先看符号位,确定是正数还是负数,如果是正数,则原码、反码、补码相同。如果是负数,则可以先-1得到反码,再符号位不变,其他位按位取反得到原码;也可以先符号位不变,其他位按位取反,再+1得到原码。注意:无符号数一律按照正数来处理。
  4. 大小端字节序分为大端字节序和小端字节序。大端字节序指的是,把高位字节处的数据存储在低地址处,把低位字节处的数据存储在高地址处。小端字节序指的是,把高位字节处的数据存储在高地址处,把低位字节处的数据存储在低地址处。
  5. 内存中使用补码来存储整数有2个好处:统一处理符号位和数值位,以及使用同一套硬件电路来把原码和反码相互转换,降低电路复杂性。

感谢大家的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/480608.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【五一创作】【数学建模】matlab的常用函数运用(1)

文章目录 1. matlab基本常识2. 常用输入输出函数2.1 输出函数2.2 拼接函数(字符串的合并)2.3 输入函数 3. 求和函数3.1 向量求和3.2 矩阵求和 4. 提取矩阵元素4.1 取第x行第y列的元素4.2 取指定行或列的所有元素4.3 取指定某些行的所有元素 1. matlab基本…

MongoDB聚合操作

文章目录 一、单一聚合二、聚合管道2.1 $match / $project / $count2.2 $limit / $skip / $sort2.3 $group 分组查询2.4 $unwind 展开数组2.5 $lookup 左外连接2.6 $bucket 存储桶 三、MapReduce 提示:以下是本篇文章正文内容,MongoDB 系列学习将会持续更…

域名解析出现错误,该如何解决?

域名作为网络地址,是我们访问网站的必经之路,域名解析就是把你的域名解析成一个ip地址,在使用的过程中遇到域名解析文件异常也是常有的事。如果域名解析出现错误,该怎么解决呢? 一、打开网页时,显示域名解析…

Redis主从复制、哨兵实战

环境:linux centos7.x ,虚拟机3台 版本:redis-6.2.6 1.下载安转redis 下载地址 wget https://download.redis.io/releases/redis-6.2.6.tar.gz解压 tar -zxvf redis-6.2.6.tar.gz移动目录 mv redis-6.2.6 /usr/local/redis编译 cd /usr/…

【GORM框架】ORM介绍、GORM简单连接和高级配置详解

博主简介:努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:数据结构、Go,Java等相关知识。博主主页: 是瑶瑶子啦所属专栏: GORM框架学习 近期目标:写好专栏的每一篇文章 目录 一、简介…

配准带尺度点云的方法汇总

如果点集之间不存在缩放关系时(即尺度相同时), 可以用经典ICP( Iterative Closest Point )方法求解得到旋转矩阵R和平移向量t来进行点集对齐。 如果存在缩放关系时,首先估计出点集S1和S2之间的缩放倍数s, 我们就可以利用ICP算法求解。 一、尺度因子s是两个点集中线…

HashSet底层原理

特点:无序、不可重复 LinkedHashSet 有序、可重复(底层通过双向链表的方式记录元素的存储顺序) HashSet底层数据结构是哈希表 jdk1.8之前:哈希表组成:数组 链表 jdk1.8之后: 数组 链表 红黑树 存储…

Flutter 组件抽取:日期(DatePicker)、时间(TimePicker)弹窗选择器【仿照】

简介 仿照《Flutter 仿ios自定义一个DatePicker》实行的日期弹窗选择器&#xff08;DatePicker&#xff09;、时间弹窗选择器&#xff08;TimePicker&#xff09; 效果 范例 class _TestPageState extends State<TestPage> {overridevoid initState() {super.initStat…

Java笔记_15(集合三)

Java笔记_15 一、创建不可变集合1.1、创建不可变集合的应用场景1.2、创建不可变集合的书写格式 二、Stream流2.1、体验Stream流2.2、Stream流的思想和获取Stream流2.3、Stream流的中间方法2.4、Stream流的终结方法2.5、收集方法collect 一、创建不可变集合 不可变集合&#xf…

山东省2023年春季高考技能测试电子技术类专业试题

注意事项 1.本试题为样题&#xff0c;实际测试试题与样题基本一致&#xff0c;不同场次试题电路装配要求会有变化&#xff0c;请考生仔细审题。 2.严禁考生私自送电&#xff0c;严禁带电操作&#xff08;通电调试除外&#xff09;。 3.考生要服从监考人员安排&#xff0c;遵…

【python入门篇】安装python教程

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; Python入门&#xff0c;本专栏主要内容为Python的基础语法&#xff0c;Python中的选择循环语句…

【GPT】AutoGPT 安装使用完全教程

欢迎关注【youcans的GPT学习笔记】原创作品&#xff0c;火热更新中** 【GPT】AutoGPT 安装使用完全教程 【GPT】AutoGPT 安装使用完全教程1. AutoGPT 介绍1.1 AutoGPT 简介1.2 AutoGPT 的工作流程 2. 下载 AutoGPT 项目源码2.1 GitHub 下载项目源码2.2 网页下载稳定版源码 3. A…

数据结构(六)—— 二叉树(1)基础

文章目录 前言一、二叉树1.1 满二叉树1.2 完全二叉树1.3 二叉搜索树1.4 平衡二叉搜索树 二、二叉树的遍历2.1 深度优先遍历&#xff08;DFS&#xff09;2.2 广度优先遍历&#xff08;BFS&#xff09; 三、二叉树的代码定义 前言 提示&#xff1a;这里可以添加本文要记录的大概…

学习路线之白银5

init background 这个阶段你就要开始正式学习c了&#xff0c; 并且了解一些常用的git操作。 C 理解程序的编译流程&#xff0c;并映射到gcc和头文件的使用中。区分头文件&#xff0c; 源码等之间的关系理解编译工具的基本使用简单掌握基本的类和函数等常见语法&#xff0c;…

MapSet

在之前数据结构的学习中&#xff0c;对于数据的查找都是基于给定一个值&#xff0c;通过和序列中的关键字比较而实现的。因此这样的查找效率一般都是更依赖于比较的次数&#xff0c;像直接遍历或二分查找都是如此。而如果我们可以不经过任何比较&#xff0c;只是通过记录的关键…

外链跳转页功能分析与实现

一个大型的正规网站&#xff0c;增加一个 外链中转页 是有必要的。合理的交互设计&#xff0c;不仅能有效保障用户体验&#xff0c;又能帮助网站收集外链数据&#xff0c;优化运营管理。 目录 1、为什么使用跳转页面来管理外链 1.1、安全性 1.2、搜索引擎优化 1.3、外链数据…

JVM学习(九):堆

一、堆&#xff08;Heap&#xff09;的概述 一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。 Java堆区在JVM启动的时候即被创建&#xff0c;其空间大小也就确定了。是JVM管理的最大一块内存空间。同时&#xff0c;堆内存的大小是可以调节的。《Java虚拟…

ESP32-硬件IIC读取温湿度传感器SHT30

简介 esp32 使用硬件I2C读取温湿度传感器SHT30,例程基于EDP-IDF-4.4.X 的I2C Simple Example 例程修改 工程创建 打开 VSCODE ,通过 查看-- 命令面板&#xff08;快捷键CtrlShiftP&#xff09;&#xff0c;打开 ESP-IDF 的例程后&#xff0c;选择 i2c_simple 例程&#xff0…

深度学习卷积神经网络学习小结

————————————————————————————————————————————— 学习小结&#xff1a; 1&#xff09;深度学习综述&#xff1b;&#xff08;2&#xff09;对卷积神经网络&#xff08;CNN&#xff09;的认识&#xff1b;&#xff08;3&#xff0…

C语言中函数宏的三种封装方式详解

目录 ​编辑 1. 函数宏介绍 3. do{...}while(0) 方式 4. ({}) 方式 5. 总结 1. 函数宏介绍 函数宏&#xff0c;即包含多条语句的宏定义&#xff0c;其通常为某一被频繁调用的功能的语句封装&#xff0c;且不想通过函数方式封装来降低额外的弹栈压栈开销。 函数宏本质上为…