little endian和big endian的概念解释,判定与用途

来源:互联网 发布:天籁2.0舒适版 知乎 编辑:程序博客网 时间:2024/05/05 10:03
 little endian和big endian是表示计算机字节顺序的两种格式,所谓的字节顺序指的是长度跨越多个字节的数据的存放形式.        假设从地址0x00000000开始的一个字中保存有数据0x1234abcd,那么在两种不同的内存顺序的机器上从字节的角度去看的话分别表示为:       1)little endian:在内存中的顺序是0x00000000-0xcd,0x00000001-0xab,0x00000002-0x34,0x00000003-0x12       2)big  endian:在内存中的顺序是0x00000000-0x12,0x00000001-0x34,0x00000002-0xab,0x00000003-0xcd       需要特别说明的是,以上假设机器是每个内存单元以8位即一个字节为单位的.       简单的说,little endian把低位存放到高位,而big endian把低位存放到低位.       现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian.              以下是判断字节存储顺序的可移植的C语言代码:       /* *******************************************************************    created:    2006-9-5    filename:     test.cpp    author:        李创        purpose:    可移植的用于判断存储格式是                little endian还是big ednian的C代码                取自<<C: A Reference Manual>>******************************************************************** */  #include  < stdio.h >  union {     long  Long;     char  Char[ sizeof ( long )];} u; int  main() {        u.Long  =   1 ;         if  (u.Char[ 0 ]  ==   1 )         {        printf( " Little Endian!\n " );    }      else   if  (u.Char[ sizeof ( long )  -   1 ]  ==   1 )     {        printf( " Big Endian!\n " );    }      else       {        printf( " Unknown Addressing!\n " );    }      printf( " Now, Let's look at every byte in the memory!\n " );     for  ( int  i  =   0 ; i  <   sizeof ( long );  ++ i)     {        printf( " [%x] = %x\n " ,  & u.Char[i], u.Char[i]);    }       return   0 ;}         很多人认为掌握这个知识是不必要,其实不然.在网络编程中,TCP/IP统一采用big endian方式传送数据,也就是说,假设现在是在一个字节顺序是little endian的机器上传送数据,要求传送的数据是0XCEFABOBO,那么你就要以0XBOBOFACE的顺序在unsigned int中存放这个数据,只有这样才能保证存放的顺序满足TCP/IP的字节顺序要求.很多时候,需要自己编写应用层的协议,字节顺序的概念在这个时候就显得及其的重要了.       下面给出的是在big endian和little endian中相互转换的代码,C语言强大的位操作的能力在这里显示了出来:         /* *******************************************************************    created:    2006-9-5    filename:     get32put32.cpp    author:        李创        purpose:    在little endian和big ednian之间相互转化数据的演示代码******************************************************************** */   #include  < stdio.h >   const  unsigned  char  SIZE_OF_UNSIGNEDINT   =   sizeof (unsigned  int ); const  unsigned  char  SIZE_OF_UNSIGNEDCHAR  =   sizeof (unsigned  char ); void  put_32(unsigned  char   * cmd, unsigned  int  data) {     int  i;     for  (i  =  SIZE_OF_UNSIGNEDINT  -   1 ; i  >=   0 ;  -- i)     {        cmd[i]  =  data  %   256 ;         //  或者可以:         // cmd[i] = data & 0xFF;          data  =  data  >>   8 ;    } }  unsigned  int  get_32(unsigned  char   * cmd) {    unsigned  int   ret;     int  i;     for  (ret  =   0 , i  =  SIZE_OF_UNSIGNEDINT  -   1 ; i  >=   0 ;  -- i)     {        ret   =  ret  <<   8 ;        ret  |=  cmd[i];            }          return  ret;}   int  main( void ) {    unsigned  char  cmd[SIZE_OF_UNSIGNEDINT];    unsigned  int  data, ret;    unsigned  char   * p;     int  i;    data  =   0x12345678 ;    printf( " data = %x\n " , data);     //  以字节为单位打印出数据      p  =  (unsigned  char * )( & data);     for  (i  =   0 ; i  <  SIZE_OF_UNSIGNEDINT;  ++ i)     {        printf( " %x " ,  * p ++ );    }     printf( " \n " );     //  以相反的顺序存放到cmd之中      put_32(cmd, data);     for  (i  =   0 ; i  <  SIZE_OF_UNSIGNEDINT;  ++ i)     {        printf( " cmd[%d] = %x\n " , i, cmd[i]);    }       //  再以相反的顺序保存数据到ret中     //  保存之后的ret数值应该与data相同      ret  =  get_32(cmd);    printf( " ret = %x\n " , ret);    p  =  (unsigned  char * )( & ret);     for  (i  =   0 ; i  <  SIZE_OF_UNSIGNEDINT;  ++ i)     {        printf( " %x " ,  * p ++ );    }     printf( " \n " );     return   0 ;}   

原创粉丝点击