【转】字节序,大小端

字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。

其实大部分人在实际的开发中都很少会直接和字节序打交道。唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。

在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian。引用标准的Big-Endian和Little-Endian的定义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
c) 网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于 TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。比如,以太网头部中2字节的“以太网帧类型”,表示后面数据的类型。对于ARP请求或应答的以太网帧类型来说,在网络传输时,发送的顺序是0x08,0x06。
栈底 (高地址)
---------------
0x06 -- 低位 
0x08 -- 高位
---------------
栈顶 (低地址)
该字段的值为0x0806。按照大端方式存放在内存中。

 

------------------------

|高地址:命令行参数和环境变量

----------------------- 0xC0000000 X86处理器
 | 栈底
 |
 |             栈
 |
 |
 |
\|/

NULL (空洞)

/|\
 |
 |
 |              堆

-----------------------
 未初始化的数据:由EXEC初始化为0或空指针 BSS
----------------(统称数据段)
初始化的数据
-----------------------  :由EXEC从程序读入
正文段(代码段)
----------------------- 正文段开始:0x08048000 X86处理器

 

 

现在我们弄清了高低地址,接着来弄清高/低字节,如果我们有一个32位无符号整型0x12345678(呵呵,恰好是把上面的那4个字节buf看成一个整型),那么高位是什么,低位又是什么呢?其实很简单。在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。

高低地址和高低字节都弄清了。我们再来回顾一下Big-Endian和Little-Endian的定义:
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位
栈底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
栈顶 (低地址)

Little-Endian: 低地址存放低位
栈底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
---------------
栈顶 (低地址)

在现有的平台上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。

三、例子

嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。

例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址  存放内容
 0x4001    0x12
 0x4000    0x34

而在Big-endian模式CPU内存中的存放方式则为:

内存地址  存放内容
 0x4001    0x34
 0x4000    0x12
 
32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址  存放内容
 0x4003     0x12
 0x4002     0x34
 0x4001     0x56
 0x4000     0x78
 
而在Big-endian模式CPU内存中的存放方式则为:

内存地址  存放内容
 0x4003     0x78
 0x4002     0x56
 0x4001     0x34
 0x4000     0x12

### 字节序的概念 字节序是指多字节数在计算机内存中的存储顺序。对于一个多字节的数据类型(如整型、浮点型等),其各个字节可能按照不同的顺序被存储到内存中。这种存储方式主要分为两大类:大端字节序(Big-Endian)和小端字节序(Little-Endina)。 #### 大端字节序 大端字节序是一种将数据的高位字节存储在低地址,而低位字节存储在高地址的方式。这种方式与人们日常书写的数字顺序一致,因此更容易被人理解。例如,假设有一个32位无符号整数 `0x12345678` 需要存储在一个按字节寻址的内存中: | 地址 | 值 | |------|-------| | 0x00 | 0x12 | | 0x01 | 0x34 | | 0x02 | 0x56 | | 0x03 | 0x78 | 在这个例子中,最高有效字节 `0x12` 被放置在最低地址位置 `0x00` 上,这正是大端字节序的特点[^1]。 #### 小端字节序 相比之下,小端字节序则采用了一种完全相反的方式来处理相同的情况——它会把数据的低位字节存放到较低的内存地址上,而高位字节则存放在较高的内存地址上。继续以上述相同的数值为例,在小端字节序下的存储情况如下所示: | 地址 | 值 | |------|-------| | 0x00 | 0x78 | | 0x01 | 0x56 | | 0x02 | 0x34 | | 0x03 | 0x12 | 可以看到,这里最显著的变化在于最低有效字节 `0x78` 已经移动到了起始地址 `0x00` 的地方[^2]。 #### 应用场景差异 不同架构的处理器可能会偏好使用其中一种特定类型的字节序作为默认设置。比如网络协议栈通常遵循的是基于TCP/IP标准的大端格式;然而像Intel x86系列微处理器家族内部操作则是依据于小端结构来执行指令集运算过程][^[^34]。 ```python def check_endianess(): num = 1 if isinstance(num, int): byte_array = bytearray((num).to_bytes(2, 'little')) return "Little Endian" if byte_array[0]==1 else "Big Endian" print(check_endianess()) ``` 上述Python脚本可以用来检测当前运行环境所支持的主要字节序列类型。如果返回值为 `"Little Endian"` 则说明该平台是以小端为主导;反之若是 `"Big Endian"` 表明此系统倾向于运用大端编码方案来进行二进制资料管理活动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值