大家可能都知道字节序里大端和小端的意思和作用。
标准的Big-Endian和Little-Endian的定义如下:
a)Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b)Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:
Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#############################################################################################################
但是为什么是这样存放呢?我们可以从内存模型的角度来理解:
首先我们要知道我们C程序映像中内存的空间布局情况:
----------------------- 最高内存地址 0xffffffff
| 栈底
.
. 栈
.
栈顶
-----------------------
|
|
/|/
NULL (空洞)
/|/
|
|
-----------------------
堆
-----------------------
未初始化的数据
----------------(统称数据段)
初始化的数据
-----------------------
正文段(代码段)
----------------------- 最低内存地址 0x00000000
我们只关注上面的栈底到栈底这一块,栈底的地址高,栈顶的地址低。
还是以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) -- 低位
---------------
栈顶 (低地址)
像这样就很好理解字节序的内存模型。
###############################################################################################################
DEC和Intel的机器(X86平台)一般采用小端。
IBM, Motorola(Power PC), Sun的机器一般采用大端。
当然,这不代表所有情况。有的CPU即能工作于小端, 又能工作于大端, 比如ARM, Alpha,摩托罗拉的PowerPC。
如何判断一个系统是big-endian还是little-endian,代码如下:
bool IsBig_Endian()
{
unsigned short test = 0x1122;
if(*( (unsigned char*) &test ) == 0x11)
return TRUE;
else
return FALSE;
还有一种方法(采用联合体):
bool isBig_Endian()
{
union My
{
int i;
char a;
}
My my;
my.i = 1;
return (my.a != 1);
}