Big/Little Endian——字节存储顺序

转自:http://hi.baidu.com/qzfukwzlvgqsvzr/item/97aba6304e9d10f82784f4d9


       嵌入式编程的面试或被面试的过程中,经常会有Little Endian与Big Endian相关的面试问题,分析区别或者写程序来判断一个CPU是Little Endian还是Big Endian。 这里做一下总结。

       一、Big Endian和Little Endian的概念

       计算机的所有内存以字节数组的方式进行编址。

       当一个逻辑上长于一个字节的整形数据放置在内存中时(比如16位,32位,和64位的整数),需要考虑这些字节的存储顺序。Little Endian: 将字节的逻辑顺序与物理顺序一致,即将逻辑上较低的字节放置在物理上较低的字节上,比如Intel x86系列;

       Big Endian字节的逻辑顺序与物理顺序相反,即将逻辑上较低的字节放置在物理上较高的字节上,比如Motorola的PowerPC以及Sun Sparc。还有一些平台同时支持两种方案,由开发者决定使用哪一种。

       例如数字0x89ABCDEF,有四个字节组成,分别为0x89, 0xAB, 0xCD, 0xEF, 相应的算术值为0x89000000,0xAB0000, 0xCD00和0xEF,很明显,0x89的值最大,称之为数字0x89ABCDEF的最高位,而0xEF为最低位。数字在内存中的存放,从低位起,有两种存放方式,如下图:

内存位置小端大端
0x....00xEF0x89
0x....10xCD0xAB
0x....20xAB0xCD
0x....30x890xEF

       

       各自的优势

        由于Little Endian提供了逻辑顺序与物理顺序的一致性,让编程者摆脱了不一致性所带来的困扰,C语言开发者可以无所顾忌的按照自己的意愿进行强制类型转换。

         但Big Endian也有其优点,尤其对于汇编程序员:他们对于任意长度的整数,总是可以通过判断Byte 0的bit-7来查看一个整数的正负(补码的首位标识正负);对于Little Endian则不得不首先知道当前整数的长度,然后查看最高byte的bit-7来判断其正负。对于这种情况,big endian的开发者可以写出非常高效的代码。

      TCP/IP协议指定其数据格式为Big endian,因此Big Endian的CPU处理起来更方面;对于Little-Endian的CPU, 如x86,应用中需要首先转换TCP/IP的数据为little endian格式。实际上,POSIX提供相应的操作函数,这些函数是htonl(), ntohl(), htons()和ntohs()。

      需要特别指出的是,通常所提到的Little Endian和Big Endian仅仅指字节顺序。


      二、如何通过程序来判断CPU为Big Endian还是Little Endian

     1. 利用union来判断

     联合中的数据成员是共享存储空间的,所分配的空间为数据成员中最大所需的内存数。union 的成员本身就被存放在相同的内存空间(共享内存,正是union 发挥作用的地方),因此,可以将一个字节型数据和一个整型数据同时作为一个union 的成员,通过如下的代码来测试endian的模式。

#include "stdio.h"

typedef union endian_test{
        int a;
        char b;

} e_t;

int main()

{
        e_t c;
        c.a = 1;

        if  (c.b)
                printf("little endian\n");
        else
                printf("big endian\n");

        return (int)c.b;

}


      2. 通过强制类型转换来判断

      将一个字节(CHAR/BYTE 类型)的数据和一个整型数据存放于同样的内存开始地址,通过读取整型数据,分析CHAR/BYTE 数据在整型数据的高位还是低位来判断CPU 工作于Littleendian 还是Big endian 模式。

#include "stdio.h"
int main(int argc, char* argv[])
{

      unsigned int num = 0;

      unsigned int *p;

      p = #

      *(unsigned char *)p = 0x1; // Set BYTE0 to 0X1

      if (num == 1)

      {

             printf("little endian\n");

      }

      else // num == 0x1000000

      {

            printf("big endian\n");

      }

      return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值