耒阳市网站建设,天津谷歌优化,品牌网站建设基本流程,中山百度网站建设本篇博客会讲解整数在内存中的存储形式#xff0c;以及整数二进制的3种表示形式#xff1a;原码、反码、补码#xff0c;还有大小端的相关知识点。相信读完本篇博客#xff0c;大家对内存的了解会上一个台阶。
注意#xff1a;本篇博客讨论的是整数在内存中的存储#x…
本篇博客会讲解整数在内存中的存储形式以及整数二进制的3种表示形式原码、反码、补码还有大小端的相关知识点。相信读完本篇博客大家对内存的了解会上一个台阶。
注意本篇博客讨论的是整数在内存中的存储像char, short, int, long, long long的有符号和无符号类型存储的都是整数。
认识原码、反码、补码
对于整数有原码、反码、补码之分它们都是整数的二进制的表示形式。有符号整数的计算方式如下
正整数的原码、反码、补码相同都是整数直接转换成二进制的结果。负整数的原码是把该数转换成二进制的结果反码和补码需要通过原码计算出来。负整数的反码的计算规则原码的符号位不变其他位按位取反得到反码。负整数的补码的计算规则反码1得到补码。
下面来举2个例子分别表示正整数和负整数。
正整数以10为例子10作为十进制数直接转换成二进制得到的就是它的原码。又因为10是正整数故原码、反码、补码相同。所以问题呢就转换成如何把十进制的10转换成二进制。
把十进制的10转换成二进制得到的是1010。这是怎么来的呢对于二进制的1010从右往左数最右边的0代表0×20倒数第二位的1代表1×21倒数第三位的0代表0×22最左边的1代表1×23所以二进制的1010就代表十进制的1×230×221×210×20802010。
严谨点来说10的默认类型是int一个int大小是4个字节也就是32个bit位应该填满32位不够在高位补0所以10的原码、反码、补码都是00000000000000000000000000001010。
再举个负数的例子-10的原码、反码、补码是多少对于负数是“有符号数”最高位表示符号位用1表示负数其余的位和10的二进制相同10000000000000000000000000001010。这就是-10的原码。
-10作为一个负数反码和补码需要通过原码来计算。反码的计算规则是原码符号位不变其他位按位取反也就是说最高位的1表示符号位不变其余位1变00变1。反码就是11111111111111111111111111110101。
补码的计算规则是反码1即是补码所以-10的补码是11111111111111111111111111110110。
整数在内存中是以哪种形式存储的呢事实上整数在内存中存储的是二进制的补码这一点是可以验证的但是同时涉及到大小端的问题。
大小端字节序
大小端字节序简称大小端指的是以字节为单位内存中的数据是如何存储的。分为2种存储方式分别是大端字节序和小端字节序简称大端和小端。
大端字节序把高位字节处的数据存储在低地址处把低位字节处的数据存储在高地址处。小端字节序把高位字节处的数据存储在高地址处把低位字节处的数据存储在低地址处。
这是什么意思呢我在VS2022环境下验证一下根据前面所讲整数在内存中存储的是补码我们来观察一下-10在内存中是如何存储的。 观察到当左边是低地址右边是高地址即地址从左到右是由低到高变化的此时内存中存储的是0x f6 ff ff ff。这是什么意思呢
整数在内存中是以二进制的补码的形式存储的。前面计算过了-10的补码是11111111111111111111111111110110。下面我们把它转换成十六进制。
先4个为一组分开1111 1111 1111 1111 1111 1111 1111 0110。
然后分别转换每一组其中1111是f0110是60x fffffff6。一个十六进制位是4个bit位2个十六进制位就是一个字节把这个数以字节为单位分隔开就是0x ff ff ff f6。
而内存中存储的却是0x f6 ff ff ff这是为什么呢在VS环境下观察内存从左到右地址是由低到高变化的也就是说本来-10补码中的高位的ff存储在了高地址处而-10补码中的低位的f6存放在低地址处这就是“小端字节序”的存储方式看起来像是数据“倒着放”。
整数在内存中的存储
整数在内存中的存储是由以下2点决定的
整数在内存中存储的是补码的二进制。根据机器是“大端字节序”还是“小端字节序”来决定是“正着放”还是“倒着放”。
以上是数据“如何存”那如何把一个数据“往外拿”呢把存的过程倒过来就行了。
根据大小端字节序把数据“正着”或者“倒着”拿出来。把拿出来的补码转换成原码。
那如何把补码转换成原码呢原码怎么转换成补码把这个过程倒过来就行了以下是如何把补码解析成有符号数的过程。
若符号位是0则是正数此时原码、反码都和补码相同。若符号位是1则是负数需要计算反码和原码。补码-1得到反码。反码的符号位不变其他位按位取反得到原码。
注意如果要解析成无符号数最高位就不是符号位了而是数据的一部分此时一律看做正整数来处理。
举个例子前面我们观察到小端机器下-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)也就是这样计算 0000000000000000000000000000000111111111111111111111111111111111100000000000000000000000000000000由于整数只能存储32个bit为最高位的1就丢了只剩下00000000000000000000000000000000得到的结果就是0。
根据以上的计算有没有发现我们根本没有管哪里是符号位哪里是数值位就是简单粗暴的把补码写出来加起来完事。CPU把内存中存储的补码拿出来进行加法运算时根本不用考虑哪里是符号位那里是数值位这就做到了把符号位和数值位统一处理。
在说第二个优点之前还需要了解一个知识点把补码转换成原码的另一种方式先把补码的符号位不变其他位按位取反再1也能得到原码。比如已知-10的补码11111111111111111111111111110110把补码的符号位不变其他位按位取反得到10000000000000000000000000001001再1得到10000000000000000000000000001010这样也得到了-10的原码。
有没有发现如果用这种方式把补码转原码那么就和原码转补码的方式相同了都是“取反再1”所以用补码来存储时把补码转原码以及原码转补码可以使用同一套硬件电路降低了电路的复杂性。
总结
整数的2进制有3种表示形式分别是原码、反码、补码。正整数的原码、反码、补码相同负整数的原码、反码、补码需要计算。把整数直接转换成2进制就是原码。负整数的原码的符号位不变、其他位按位取反得到反码。负整数的反码1得到补码。从补码转原码需要先看符号位确定是正数还是负数如果是正数则原码、反码、补码相同。如果是负数则可以先-1得到反码再符号位不变其他位按位取反得到原码也可以先符号位不变其他位按位取反再1得到原码。注意无符号数一律按照正数来处理。大小端字节序分为大端字节序和小端字节序。大端字节序指的是把高位字节处的数据存储在低地址处把低位字节处的数据存储在高地址处。小端字节序指的是把高位字节处的数据存储在高地址处把低位字节处的数据存储在低地址处。内存中使用补码来存储整数有2个好处统一处理符号位和数值位以及使用同一套硬件电路来把原码和反码相互转换降低电路复杂性。
感谢大家的阅读