字节序
了解什么是字节顺序前,先复习一下单位换算的基本概念。
位(bit):计算机中的最小数据单位,计算机存储的都是二进制0和1这两个鬼。
字节(Byte):字节是存储空间的基本计量单位,也是内存的基本单位,也是编址单位。例如,一个计算机的内存是4GB,就是该计算机的内存中共有4×1024×1024×1024个字节,意味着它有4G的内存寻址空间。
换算关系:
1 GB = 1024 MB
1 MB = 1024 KB
1 KB = 1024 Bytes
1 Byte = 8 bits
思考个问题,通常描述32位二进制数据,为什么是用8个十六进制数呢?如0x1A2B3C4D
4个二进制bit 表示的数值范围是从【0000 - 1111】,即【0 - 15】, 刚好等同于 一位 16进制数的数值范围0~F(15),也就是说,4个二进制位(bit) = 1个十六进制(Hex),8个二进制位(bit) = 一个字节(Byte) = 2个十六进制(hex),32个二进制位(bit) = 四个字节(Byte) = 8个十六进制(hex)。
所以针对一个32位的二进制数值,通常十六进制来表示,如0x1A2B3C4D,总共四个字节,两个十六进制数表示一个字节,高位字节为0x1A,低位字节为0x4D;中间两个字节分别为0x2B和0x3C;
数值0x1A2B3C4D想要在计算机中正确使用,就必须要考虑在内存中将其对应的四个字节合理存储。假设内存的地址都是从低到高分配的,那么对于一个数值多个字节顺序存储就有两种存储方式:
方式一:数值的高位字节存放在内存的低地址端,低位字节存放在内存的高地址端:
内存低地址 ——————–> 内存高地址
0x1A | 0x2B | 0x3C | 0x4D
高位字节 <——————– 低位字节
方式二、数值的低位字节存放在内存的低地址端,高位字节存放在内存的高地址端:
内存低地址 ——————–> 内存高地址
0x4D | 0x3C | 0x2B | 0x1A
低位字节 ——————–> 高位字节
方式一 ,我们就称之为 大端(Big endian
)模式;即数值高位字节放在内存的低地址端,低位字节放在内存的高地址端。
方式二 ,我们就称之为 小端(Little endian
)模式;即数值低位字节放在内存的低地址端,高位字节放在内存的高地址端。
画图更直观理解一下:
总结
大端小端是不同的字节顺序存储方式,统称为字节序;
大端模式,是指数据的高字节位 保存在 内存的低地址中,而数据的低字节位 保存在 内存的高地址中。这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。和我们”从左到右“阅读习惯一致。
小端模式,是指数据的高字节位 保存在 内存的高地址中,而数据的低字节位 保存在 内存的低地址中。这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
优缺点
Big-Endian 优点:靠首先提取高位字节,你总是可以由看看在偏移位置为0的字节来确定这个数字是正数还是负数。你不必知道这个数值有多长,或者你也不必过一些字节来看这个数值是否含有符号位。这个数值是以它们被打印出来的顺序存放的,所以从二进制到十进制的函数特别有效。因而,对于不同要求的机器,在设计存取方式时就会不同。
Little-Endian 优点:提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。
如果你增加数字的值,你可能在左边增加数字(高位非指数函数需要更多的数字)。因此,经常需要增加两位数字并移动存储器里所有Big-endian顺序的数字,把所有数向右移,这会增加计算机的工作量。不过,使用Little- Endian的存储器中不重要的字节可以存在它原来的位置,新的数可以存在它的右边的高位地址里。这就意味着计算机中的某些计算可以变得更加简单和快速。
网络字节顺序
1、字节内的比特位不受这种顺序的影响
比如一个字节 1000 0000 (或表示为十六进制 80H)不管是什么顺序其内存中的表示法都是这样。
2、大于1个字节的数据类型才有字节顺序问题
比如 Byte A,这个变量只有一个字节的长度,所以根据上一条没有字节顺序问题。所以字节顺序是“字节之间的相对顺序”的意思。
3、大于1个字节的数据类型的字节顺序有两种
比如 short B,这是一个两字节的数据类型,这时就有字节之间的相对顺序问题了。
网络字节顺序是“所见即所得”的顺序。而Intel类型的CPU的字节顺序与此相反。
比如上面的 short B=0102H(十六进制,每两位表示一个字节的宽度)。所见到的是“0102”,按一般数学常识,数轴从左到右的方向增加,即内存地址从左到右增加的话,在内存中这个 short B的字节顺序是:
01 02
这就是网络字节顺序。所见到的顺序和在内存中的顺序是一致的!
假设通过抓包得到网络数据的两个字节流为:01 02
*而相反的字节顺序就不同了,其在内存中的顺序为:02 01
*
如果这表示两个 Byte类型的变量,那么自然不需要考虑字节顺序的问题。如果这表示一个 short 变量,那么就需要考虑字节顺序问题。根据网络字节顺序“所见即所得”的规则,这个变量的值就是:0102
假设本地主机是Intel类型的,那么要表示这个变量,有点麻烦:
定义变量 short X,字节流地址为:pt,按顺序读取内存是为x=((short)pt);
那么X的内存顺序当然是 01 02按非 “所见即所得” 的规则,这个内存顺序和看到的一样显然是不对的,所以要把这两个字节的位置调换。调换的方法可以自己定义,但用已经有的API还是更为方便。
网络字节顺序与主机字节顺序
- 网络字节顺序NBO(Network Byte Order):按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
- 主机字节顺序(HBO,Host Byte Order):不同的机器HBO不相同,与CPU设计有关计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换。
“本篇文章主要摘自参考资料”
最后更新: 2020年12月06日 14:18