endianess(字节次序)

发布于 2014-11-19  1.37k 次阅读


1. 基础

在解释Endianess前,需要先明白几个基础定义

1) 数据的高位与低位是什么

以1001001为例,则从左边算起是 高位 -> 低位, 简而言之就是左边是高位,右边是低位

而内存中一般来说是以字节为单位来表示数据,所以对于数字 int 型 0x12345678 来说如下

2) 多字节数据在内存中的存储地址表示

一般来说我们表示某个数据的内存地址都是取它的内存地最低位置地址表示,例如a = 0x1234567占据了内存的地址0x100,0x101,0x102,0x103四个字节,则a的内存地址为0x100

 

2. Endianess的定义

Endianess指的是字节在在内存中的存储次序,一般可分为

  • Big Endian: 高位优先(大端)存储, 内存的最低位地址存储数据的最高位数据
  • Little Endian: 低位优先(小端)存储, 内存的最低位地址存储数据的最低位数据

举例如下,还是以0x123456为例

 

可见实际上大端存储更符合正常人的阅读顺序。

 

3. 现实中对Endianess的使用

以下内容摘自网上

DEC (Digital Equipment Corporation,现在是Compaq公司的一部分)和Intel的机器(X86平台)一般采用小端。

IBM, Motorola(Power PC), Sun的机器一般采用大端。

当然,这不代表所有情况。有的CPU即能工作于小端, 又能工作于大端, 比如ARM, Alpha,摩托罗拉的PowerPC。 具体情形参考处理器手册。

具体这类CPU是大端还是小端,应该和具体设置有关。
如,Power PC支持little-endian字节序,但在默认配置时是big-endian字节序)一般来说,大部分用户的操作系统(如windows, FreeBsd,Linux)是Little Endian的。少部分,如MAC OS ,是Big Endian 的。
所以说,Little Endian还是Big Endian与操作系统和芯片类型都有关系。
Linux系统中,你可以在/usr/include/中(包括子目录)查找字符串BYTE_ORDER(或_BYTE_ORDER, __BYTE_ORDER),确定其值。BYTE_ORDER中文称为字节序。这个值一般在endian.h或machine/endian.h文件中可以找到,有时在feature.h中,不同的操作系统可能有所不同

 

4. 为什么要注意字节序的问题

以下内容摘自网上

  你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而 JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA 采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。

无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。


公交车司机终于在众人的指责中将座位让给了老太太