字节序和大小端

1. 字节顺序

字节顺序(Endian) 

  字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。

   计算机系统一般采用字节(Byte(8 bit ))作为逻辑寻址单位。当物理单位的长度大于1个字节时,就要区分字节顺序(Byte Order)。常见的字节顺序有两种:Big Endian(High-byte first)Little Endian(Low-byte first)Intel X86平台采用Little Endian,而PowerPC处理器则采用了Big Endian 

   endian指的是当物理上的最小单元比逻辑上的最小单元小时,逻辑到物理的单元排布关系。咱们接触到的物理单元最小都是byte,在通信领域中,这里往往是bit

 

2. 最高有效位、最低有效位

最高有效位(MSB: Most Significant Bit)

  最高有效位(MSB),是指最左边的位,是在一个n位二进制数字中的n-1位,这个位有最高的权重(2^(n-1))。第一个或最左边的位,当这个数字被用一般的方式书写时。

 

最低有效位(LSB: Least Significant Bit)

  最低有效位(LSB),是指最右边的位,因为写较不重要的数字到右边位置符号的协定。类似于一个十进制整数的最不重要的数字,它是在一个(最右边)位置的数字。

 

3. 大小端

小端Little endian低字节存放在低地址

  低地址存放最低有效位(LSB),既低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

 

大端Big endian:高字节存储在低地址

  低地址存放最高有效位(MSB),既高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

  

  例子:比如数字0x12345678(双字、四字节)在两种节序CPU中的存储顺序如下所示:

  Little Endian                                           
     低地址 --------------------------------------> 高地址
     -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     78     |    56     |     34     |     12     |
     -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  Big Endian                                           
     低地址 --------------------------------------> 高地址
     -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     12     |    34     |     56     |     78     |
     -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

  1. 多字节数据才有大小端序列。单字节(如char)不考虑字节序大小端。
  2. Big Endian判别一个数的正负很容易,只要取低地址的第一个字节就能确认。Little Endian长度为1,2,4字节的数,排列方式都是一样的,数据类型转换非常方便。
  3. little-endian 最符合人的思维的字节序(地址低位存储值的低位,地址高位存储值的高位)。低位值小,就应该放在内存地址小的地方;高位值就应该放在内存地址大的地方。
    big-endian 最直观的字节序(地址低位存储值的高位,地址高位存储值的低位)只需要把内存地址从左到右按照由低到高的顺序写出 
 
C++判断主机是大小端
//方法一:
//1.原理:多字节类型强制转换类型成单字节,char单字节指向多字节低地址,即可判断大小端
const int endian = 1;
#define isBigEndian()        ( (*(char*) &endian) == 0 )    //true大端
#define IsLittleEndian()    ( (*(char*) &endian) == 1 )    //true小端

//2.原理:将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)
void IsBigEndian()
{
    short a = 0x1122;        //十六进制,一个数值占4位
    char b = *(char *)&a;    //通过将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)
    if( b == 0x11)            //低字节存的是数据的高字节数据
    {
        printf("大端模式");    //是大端模式
    }
    else
    {
        printf("小端模式");    //是小端模式
    }
}

//方法二:
//原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间
void IsBigEndian()
{
    union temp
    {
        short int a;
        char b;
    }temp;
    temp.a = 0x1234;
    if( temp.b == 0x12 )    //低字节存的是数据的高字节数据
    {
        printf("大端模式");    //是大端模式
    }
    else
    {
        printf("小端模式");    //是小端模式
    }
}

 

 

4. 网络字节序、主机序

网络字节序(Network Order)

  TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。

 

主机序(Host Orader)

  整数在内存中保存的顺序,它遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序(Little-Endian)和网络序(Big-Endian)的转换。

  

  1. 在网络程序开发时 或是跨平台开发时,要注意通信双方协商好字节序。

  2. 节序转换的函数:
    htons (host to network unsigned short) 把unsigned short类型从主机序转换到网络序
    htonl (host to network unsigned long) 把unsigned long类型从主机序转换到网络序
      ntohs (network to host unsigned short) 把unsigned short类型从网络序转换到主机序
    ntohl (network to host unsigned long) 把unsigned long类型从网络序转换到主机序  

 

  欢迎转载,转载请注明出处,谢谢!

 

posted @ 2013-04-10 00:38  子韦一  Views(1318)  Comments(0Edit  收藏  举报