美文网首页
大端序和小端序

大端序和小端序

作者: 夜空中乄最亮的星 | 来源:发表于2021-09-22 15:05 被阅读0次

为什么有大小端之分

我一直都不理解,为什么要有大小端区分,尤其是小端,总是会忘记,因为他不符合人类的思维习惯,但存在即为合理,存在就有他存在的价值。这里有一个比较合理的解释:

计算机中电路优先处理低位字节,效率比较高,因为计算机都是从低位开始的,所以计算机内部处理都是小端字节序。

但是我们平常读写数值的方法,习惯用大端字节序,所以除了计算机的内部,其他场景大都是大端字节序,比如:网络传输和文件储存时都是用的大端字节序。所以大小端问题很可能与硬件或者软件的创造者们有关,实际在计算机工业应用上,不同的操作系统和不同的芯片类型都有所不同。不同的系统设计不同,所以我们也没必要深究为什么要有这个区分,只需要知道他们的原理就好了。

什么是大端、小端

大端模式:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端;

小端模式:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端;

这么说也有点模糊,还是配个图来看更清晰:

我们来看一看数值0x1A2B3C4D在大端与小端的表现形式,这里我们假设地址是从0x4000开始:

image.png

上图所示:大端和小端的字节序最小单位是1字节(8bit),大端字节序就和我们平时的写法顺序一样,从低地址到高地址写入0x1A2B3C4D,而小端字节序就是我们平时的写法反过来,因为字节序最小单位为1字节,所以从低地址到高地址写入0x4D3C2B1A

因为大端、小端很容易混记,所以分享一个我自己记忆的小技巧:

大端高低高低,也就是高位字节排放在内存低地址端,高地址端存在低位字节

小端高高低低;也就是高位字节排放在内存的高地址端,低位字节排放在内存的低地址端

大小端字节序转化

大小端的转换其实还算比较简单,通过位操作就可以实现,这里我们用uint32类型作为例子:

func SwapEndianUin32(val uint32)  uint32{
    return (val & 0xff000000) >> 24 | (val & 0x00ff0000) >> 8 |
        (val & 0x0000ff00) << 8 | (val & 0x000000ff) <<24
}

其实go官方库encoding/binary中已经提供了大小端使用的库,我们要想进行大小端转换,完全可以使用官方库,没必要自己造轮子。我们看一下这个库怎么使用:

// use encoding/binary
// bigEndian littleEndian
func BigEndianAndLittleEndianByLibrary()  {
    var value uint32 = 10
    by := make([]byte,4)
    binary.BigEndian.PutUint32(by,value)
    fmt.Println("转换成大端后 ",by)
    fmt.Println("使用大端字节序输出结果:",binary.BigEndian.Uint32(by))
    little := binary.LittleEndian.Uint32(by)
    fmt.Println("大端字节序使用小端输出结果:",little)
}
// 结果:
转换成大端后  [0 0 0 10]
使用大端字节序输出结果: 10
大端字节序使用小端输出结果: 167772160

grpc中对大端的应用

大家对gRPC一定很熟悉,最近在看gRPC源码时,看到gRPC封装message时,在封装header时,特意指定了使用大端字节序,源码如下:

// msgHeader returns a 5-byte header for the message being transmitted and the
// payload, which is compData if non-nil or data otherwise.
func msgHeader(data, compData []byte) (hdr []byte, payload []byte) {
    hdr = make([]byte, headerLen)
    if compData != nil {
        hdr[0] = byte(compressionMade)
        data = compData
    } else {
        hdr[0] = byte(compressionNone)
    }

    // Write length of payload into buf
    binary.BigEndian.PutUint32(hdr[payloadLen:], uint32(len(data)))
    return hdr, data
}

总结

  • 大端小端是不同的字节顺序存储方式,统称为字节序
  • 大端:是指数据的高字节位 保存在 内存的低地址中,而数据的低字节位 保存在 内存的高地址中。这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。和我们”从左到右“阅读习惯一致。
  • 小端:是指数据的高字节位 保存在 内存的高地址中,而数据的低字节位 保存在 内存的低地址中。这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致
  • 区分:计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读区字节,先读取第一个字节,再读取第二个字节,所以说我就可以根据这个特性来读判断大小端。
  • 转换:通过位操作就可以实现,具体可以使用标准库encoding/binary;

相关文章

  • 大端序和小端序

    1、概念 字节序,又称端序,英文名称Endianness。字节序是指存放多字节(byte)数据的顺序。多用于整数在...

  • 大端序和小端序

    大端序 高位字节存储在最低的内存地址处,这种存储顺序称为大端序.假设内存地址增长方向为从左至右-->,一个32位的...

  • 大端序和小端序

    为什么有大小端之分 我一直都不理解,为什么要有大小端区分,尤其是小端,总是会忘记,因为他不符合人类的思维习惯,但存...

  • go's io

    大端序就是把数据高字节存贮到内存低地址中,小端序反之。

  • C语言进阶

    字节序 由于历史原因,业界存在两种字节序标准,大字序(大端)和小字序(小端);大字序,高字节存在低地址;小字序,高...

  • (转)字节序、大端序与小端序及其相关转换

    字节序、大端序与小端序及其相关转换https://blog.csdn.net/SwordArcher/articl...

  • C: 判断大小端

    大端与小端 大端与小端指的是多字节的数值在内存中的存储形式,数值的起始存储在内存的高序地址则为大端,反之为小端: ...

  • 简单程序判断大端小端

    小端和大端的区别:描述多字节变量在内存中的存放方向;小端就是低序字节放在高位地址,大端则相反; 验证程序: 原理

  • golang之大端序、小端序

    一、概述 字节序:字节在电脑中存放时的序列与输入/输出时的序列;也指的是存放多字节数据的字节(byte)的顺序,典...

  • C++网络编程小心得

    网络当前总结 (乱入)split 字符串 socket 传输字节序问题 由于进行网络传输涉及到大端序小端序问题,基...

网友评论

      本文标题:大端序和小端序

      本文链接:https://www.haomeiwen.com/subject/odxggltx.html