如何理解小端(Little-endian)与大端(Big-endian)

大家可能都知道字节序里大端和小端的意思和作用。

标准的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;

} //IsBig_Endian()
还有一种方法(采用联合体):
bool isBig_Endian()
{
    union My
    {
        int  i;
        char a;
    }
    My my;
    my.i = 1;
    return (my.a != 1);
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值