大小端问题

来源:互联网 发布:淘宝女西装外套 编辑:程序博客网 时间:2024/06/05 19:00
1、大小端解析
        端模式出自Jonathan Swift书写的《格列佛游记》一书,这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big Endian,从尖头开始将鸡蛋敲开的人被归为Littile Endian。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。
        在计算机业Big Endian和Little Endian也几乎引起一场战争。在计算机业界,Endian表示数据在存储器中的存放顺序。
        大端:高位存在低地址,低位存在高地址;
        小端:高位存在高地址,低位存在低地址;(intel的x86,ARM普遍都是属于小端)


        举个例子,从内存地址0x0000开始有以下数据
        0x0000    0x12
        0x0001    0x34
        0x0002    0xab
        0x0003    0xcd

    
        如果我们去读取一个地址为0x0000的四个字节变量:
                若字节序为big-endian,则读出结果为0x1234abcd;
                若字节序位little-endian,则读出结果为0xcdab3412.

        如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为:
                         big-endian      little-endian
        0x0000          0x12                  0xcd
        0x0001          0x23                  0xab
        0x0002          0xab                  0x34
        0x0003          0xcd                  0x12

        
        Intelx86系列以及ARM系列CPU都是little-endian的字节序.

2、    大小端问题的解决
       (1) 下面贴一个很简单的判断大小端的函数
[cpp] view plaincopyprint?
  1. int checkCPUendian()//返回1,为小端;反之,为大端;  
  2. {  
  3.     union  
  4.     {  
  5.         unsigned int  a;  
  6.         unsigned char b;  
  7.     }c;  
  8.     c.a = 1;  
  9.     return 1 == c.b;  
  10. }  

       (2) 大端模式处理器的字节序到网络字节序不需要转换,此时ntohs(n)=n,ntohl =n;而小端模式处理器的字节序到网络字节必须要进行转换(同理,有时候需要将大端字节顺序转换成小端字节顺序,也用这个函数,因为这个函数本来就是用来颠倒字节顺序的),转换如下:

  

[cpp] view plaincopyprint?
  1. #if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)  
  2.   
  3.   
  4.    #define htons(A)  (A)  
  5.    #define htonl(A)  (A)  
  6.    #define ntohs(A)  (A)  
  7.    #define ntohl(A)  (A)  
  8.   
  9.   
  10. #elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)  
  11.   
  12.   
  13.    #define htons(A)  ((((uint16_t)(A) & 0xff00) >> 8 ) | \\  
  14.                       (((uint16_t)(A) & 0x00ff) << 8 ))  
  15.    #define htonl(A)  ((((uint32_t)(A) & 0xff000000) >> 24)  | \\  
  16.                       (((uint32_t)(A) & 0x00ff0000) >> 8 )  | \\  
  17.                       (((uint32_t)(A) & 0x0000ff00) << 8 )  | \\  
  18.                       (((uint32_t)(A) & 0x000000ff) << 24))  
  19.    #define ntohs     htons  
  20.    #define ntohl     htohl  
  21.   
  22.   
  23. #else  
  24.   
  25.   
  26.    #error Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both.  
  27.   
  28.   
  29. #endif  
原创粉丝点击