Skip to content

0920字节数组的表示规则(3)大小端问题

ziyouzy edited this page Sep 20, 2020 · 2 revisions

大小端的本质是个数据排列规则问题

先不管这个,先举个例子:

如果存在一个非常大,位数非常多的16进制数:

0XC1C2C3C4C5C6C7C8C9C0CACBCCCDCE

首先,他用一个字节是肯定无法储存的,一个字节可以理解成是个“房子”,这个房子装不下他

之后再从另一个方面考虑这个问题:

目前我知道计算机硬件储存数据都是通过一个个连续的内存空间来储存数据的,每一个内存空间的大小都是固定的,也都有各自的内存地址标识

这个内存地址标识也就是可以用&拿到的具体值

如果把这每个内存空间也比作是房子的化,这个房子就会是更具有“物理属性的房子”,而这个房子的面积有多大呢?

其实就是32位计算机和64位计算机的区别了,目前房子的大小是64个bit,他代表了机器的硬件层,内存与处理器通信之间的"宽度"

可以储存8个字节,或者是16个ascii码

回到宽度这个问题,不仅仅是本地内存与处理器之间通信的宽度,在进行网络传输之前,稳妥起见也可以将每个物理层面的房子进行一下大小端的序列化操作

也就是说,先将在本地每个内存块里的数据用大端或小端的规则排序一下,在进行传输,才会比较优雅

或者说,如果一个内存块里的数据本身就是大端规则,过滤后不会变,而反之则会变为大端

所谓物理房子的大小,有个学名叫做:

寄存器宽度

====

百度的官方解释:

大小端模式

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于 大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以随时在程序中(在ARM Cortex 系列使用REV、REV16、REVSH指令 [1] )进行大小端的切换。

而观察一下golang中具体工具的用法:

crc16 :=uint16(256) int16buf := new(bytes.Buffer) //构建int16 输出,int16buf的数据类型是一个字节数组
binary.Write(int16buf,binary.LittleEndian,crc16)

其实bytes.Buffer底层就是一个 []byte, 字节切片,文章:

https://blog.csdn.net/txj236/article/details/52130439

显而易见的binary.Write()是一个用来将数据写入寄存器的标准化方法,写入的同时可以设置大小端格式

同时从这个方法可知,golang将写入寄存器的数据格式规定成了byte数组

而crc16是个uint16数据类型的数据,不能直接写入寄存器,需要先进行转换

于是用了转换函数binary.Write(),同时规定了其在每个寄存器内的排列规则都是LittleEndian模式

Clone this wiki locally