相关文章推荐
眼睛小的米饭  ·  张静初主演电影《脱轨时代》--传媒--人民网·  7 月前    · 
卖萌的松树  ·  李沁个人资料介绍简介_头条·  1 年前    · 
发呆的石榴  ·  臨風書軒~痞子蔡「愛爾蘭咖啡」·  1 年前    · 
帅气的鸵鸟  ·  (宣讲会因疫情取消)广东省能源集团有限公司宣 ...·  1 年前    · 
阳光的蟠桃  ·  天价片酬没演技?这档节目教“流量明星”如何成 ...·  1 年前    · 
小百科  ›  什么是大端序和小端序,为什么要有字节序-腾讯云开发者社区-腾讯云
小端序(little-endian) printf 字节序
踢足球的卡布奇诺
1 年前
作者头像
KevinYan
0 篇文章

什么是大端序和小端序,为什么要有字节序

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 网管叨bi叨 > 正文

什么是大端序和小端序,为什么要有字节序

发布 于 2021-03-16 15:49:48
7.1K 0
举报

什么是字节序

字节序 ,又称 端序 或 尾序 (英语中用单词: Endianness 表示),在计算机领域中,指电脑内存中或在数字通信链路中,占用多个字节的数据的字节排列顺序。

在几乎所有的平台上,多字节对象都被存储为连续的字节序列。例如在 Go 语言中,一个类型为 int 的变量 x 地址为 0x100 ,那么其指针 &x 的值为 0x100 。且 x 的四个字节将被存储在内存的 0x100, 0x101, 0x102, 0x103 位置。

字节的排列方式有两个通用规则:

  • 大端序(Big-Endian)将数据的低位字节存放在内存的高位地址,高位字节存放在低位地址。这种排列方式与数据用字节表示时的书写顺序一致,符合人类的阅读习惯。
  • 小端序(Little-Endian),将一个多位数的低位放在较小的地址处,高位放在较大的地址处,则称 小端序 。小端序与人类的阅读习惯相反,但更符合计算机读取内存的方式,因为CPU读取内存中的数据时,是从低地址向高地址方向进行读取的。

上面的文字描述有点抽象,我们拿一个例子来解释一下字节排列时的大端序和小端序。

在内存中存放整型数值 168496141 需要4个字节,这个数值的对应的16进制表示是 0X0A0B0C0D ,这个数值在用大端序和小端序排列时的在内存中的示意图如下:

大端序和小端序

为何要有字节序

很多人会问,为什么会有字节序,统一用大端序不行吗?答案是,计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以, 计算机的内部处理都是小端字节序。在计算机内部,小端序被广泛应用于现代 CPU 内部存储数据;而在其他场景,比如网络传输和 文件存储 则使用大端序 。

Go语言对字节序的处理

Go 语言存储数据时的字节序依赖所在平台的 CPU,处理大小端序的代码位于 encoding/binary ,包中的全局变量 BigEndian 用于操作大端序数据, LittleEndian 用于操作小端序数据,这两个变量所对应的数据类型都实现了 ByteOrder 接口。

package main
import (
 "encoding/binary"
 "fmt"
 "unsafe"
const INT_SIZE = int(unsafe.Sizeof(0)) //64位操作系统,8 bytes
//判断我们系统中的字节序类型
func systemEdian() {
 var i = 0x01020304
 fmt.Println("&i:",&i)
 bs := (*[INT_SIZE]byte)(unsafe.Pointer(&i))
 if bs[0] == 0x04 {
  fmt.Println("system edian is little endian")
 } else {
  fmt.Println("system edian is big endian")
 fmt.Printf("temp: 0x%x,%v\n",bs[0],&bs[0])
 fmt.Printf("temp: 0x%x,%v\n",bs[1],&bs[1])
 fmt.Printf("temp: 0x%x,%v\n",bs[2],&bs[2])
 fmt.Printf("temp: 0x%x,%v\n",bs[3],&bs[3])
func testBigEndian() {
 var testInt int32 = 0x01020304
 fmt.Printf("%d use big endian: \n", testInt)
 testBytes := make([]byte, 4)
 binary.BigEndian.PutUint32(testBytes, uint32(testInt))
 fmt.Println("int32 to bytes:", testBytes)
 fmt.Printf("int32 to bytes: %x \n", testBytes)
 convInt := binary.BigEndian.Uint32(testBytes)
 fmt.Printf("bytes to int32: %d\n\n", convInt)
func testLittleEndian() {
 var testInt int32 = 0x01020304
 fmt.Printf("%x use little endian: \n", testInt)
  testBytes := make([]byte, 4)
 binary.LittleEndian.PutUint32(testBytes, uint32(testInt))
 fmt.Printf("int32 to bytes: %x \n", testBytes)
 convInt := binary.LittleEndian.Uint32(testBytes)
 fmt.Printf("bytes to int32: %d\n\n", convInt)
func main() {
 systemEdian()
 fmt.Println("")
 testBigEndian()
 testLittleEndian()

运行上面的程序会在终端里输出

&i: 0xc000084000
system edian is little endian
temp: 0x4,0xc000084000
temp: 0x3,0xc000084001
temp: 0x2,0xc000084002
temp: 0x1,0xc000084003
16909060 use big endian: 
int32 to bytes: [1 2 3 4]
int32 to bytes: 01020304 
 
推荐文章
眼睛小的米饭  ·  张静初主演电影《脱轨时代》--传媒--人民网
7 月前
卖萌的松树  ·  李沁个人资料介绍简介_头条
1 年前
发呆的石榴  ·  臨風書軒~痞子蔡「愛爾蘭咖啡」
1 年前
帅气的鸵鸟  ·  (宣讲会因疫情取消)广东省能源集团有限公司宣讲会- 广东工业大学 ...
1 年前
阳光的蟠桃  ·  天价片酬没演技?这档节目教“流量明星”如何成为好演员!_百科TA说
1 年前
Link管理   ·   51好读   ·   Sov5搜索   ·   小百科
小百科 - 百科知识指南