整数的无符号编码和有符号编码
Posted shuiyonglewodezzzzz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整数的无符号编码和有符号编码相关的知识,希望对你有一定的参考价值。
单个的位没有实际意义,加上解释才有实际意义.我们可以把位组合在一起,并且加上解释以此赋予它意义.
无符号编码表示的数 x >= 0
有符号编码表示的数 min <= x and x <= max
当我们对数字的运算超出编码所能表示的范围就叫做溢出.
大多数计算机使用8位的块(字节)作为最小的可寻址单位.机器级程序将内存视为非常大的数组,称为虚拟内存.内存中的每一个字节都由唯一的数字来标识.称为它的地址.
所有地址的集合即为虚拟地址空间.所以,对于32位的机器,虚拟地址空间地址范围为0~0x8FFFFFFF-1,从0开始,需要减去1.
1.二进制转16进制
数学原理: 2^0+2^1+2^2+2^3 = 15
在16进制中我们使用A~F来表示10,11,12,13,14,15,0~9 不变.
由此,对一个二进制序列,我们只要从低位开始,每四个位取一个16进制数.如下.
1111 0001 1000 的16进制表示法为 0xF18
如果最后一次取数的二进制序列少于4位,高位补0,如下
11 0001 1000 的16进制表示法为 0x318
特别当x = 2^n次方时,转16进制方法如下.
因为有16进制的0代表4个二进制位.所以n = i + 4j. i = 0,1,2,3,16进制表示法为0x(2^i)(j个0)
比如 二进制序列 100 0000 是 2^6, 6 = 2+1*4,16进制表示法为0x40
2.16进制转二进制
每一个16进制数,写成4个二进制位
比如.0x7F 0111 1111
对于一个多字节的程序对象,必须建立俩个规则,对象的地址是什么,内存中如何排列这些字节,假设4字节int变量0x7FFFFFFF存储是连续的,
有俩种排列方式.
1.低位在前
0x00 int的第一个字节 FF
0x01 int的第二个字节 FF
0x02 int的第三个字节 FF
0x03 int的第四个字节 7F
2.高位在前
0x00 int的第四个字节 7F
0x01 int的第三个字节 FF
0x02 int的第二个字节 FF
0x03 int的第一个字节 FF
由此我们导出俩种程序对象在内存中排列的方式,大端法,小端法
1.有效的低字节在前,小端法
2.有效的高字节在前.大端法
影响到三个方面.
1.跨主机传送数据,比如从使用大端排列的机器传输字节到小端排列的机器.如下,假设要传送的数据是4个字节的int数字,0x7FFFFFFF(人的书写形式),即2147483647
大端机器的操作如下,将此int的四个字节,存入到一个bye[4]的数组内.[7F,FF,FF,FF,FF,FF,FF],
小端机器接受到数据如下.[7F,FF,FF,FF,FF,FF,FF],那么小端机器认为低字节在前,即传输过来的数字为0xFFFFFFF7F.
2.阅读表示整数数据的字节序列时字节顺序也很重要.如下,考虑到反汇编代码
01 05 43 0b 20 00,这个是我们的书写顺序.
小端机器解释的顺序为 00 20 0b 43 05 01
大端机器解释的顺序为 01 05 43 0b 20 00
3.编写规避正常类型系统的程序时,比如C里面的强制转换和union
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
无符号数编码和有符号整数补码编码
设一个二进制序列[xw-1.........x0]
无符号编码,最高位为负权,即符号位:
X1 = xw-1*2w-1+..........+x0*20
有符号补码编码为:
X2 = -xw-1*2w-1+xw-2*2w-2+......................+x0*20
由以上俩个数学公式,可以导出有符号补码编码整数转无符号编码整数公式
X2-X1 = -xw-1 * 2w-1 - xw-1*2w-1 = -xw-1*2w
即 X1 = X2 + xw-1*2w X2 = X1 - xw-1*2w
设,w = 4,考虑如下一个二进制序列[ 1 0 1 1]
它的无符号整数为 8+2+1=11,有符号整数为 -8+3=-5,
有 -5 = 11 - 1*2^4=11-16=-5
有 11 = -5 + 2^4 = -5 + 16 = 11
对俩个整数相加溢出,即超出编码能容纳的范围,
无符号数加法
x +y = x+y 或者 x + y - 2w(即溢出位舍弃),考虑如下代码
#include <iostream> #include<limits.h> using namespace std; int main() { cout << UINT32_MAX + 1 << endl; }
运行结果为0.原理如下
0xFFFFFFFF + 1 = 0x1 00000000,溢出舍弃,即0x00000000 = 0x1 00000000 - 2^32 = 2^32 - 2^32
有符号数补码加法
x + y = x +y 或者 x+y - 2w (正溢出,整数相加变成负数) 或者 x+y + 2w (负数相加变成整数)
int main() { cout << INT32_MAX + 1 << endl; //2147483647 + 1 = 2147483648 - 2^32 = -2147483648
cout << INT32_MIN - 1 << endl; // -2147483648 - 1 = -2147483649 + 2^32 = 2147483647
}
INT32_MAX 是 0x7FFFFFFF + 1 = 0x80000000 - 0x1 00000000 (2^32) = 0x80000000,第二行同理
以上是关于整数的无符号编码和有符号编码的主要内容,如果未能解决你的问题,请参考以下文章
如何对实际上是 int[] 的无符号字节数组进行 base64 编码