cpu字节序(整理)

来源:互联网 发布:淘宝推广赚佣金 编辑:程序博客网 时间:2024/05/18 01:43
字节序不是由操作系统决定的,而是由cpu架构决定的
CPU架构是CPU厂商给属于同一系列的CPU产品定的一个规范,主要目的是为了区分不同类型CPU的重要标示。目前市面上的CPU指令集分类主要分有两大阵营,一个是intel、AMD为首的复杂指令集CPU,另一个是以IBM、ARM为首的精简指令集CPU。两个不同品牌的CPU,其产品的架构也不相同,例如,Intel、AMD的CPU是X86架构的,而IBM公司的CPU是PowerPC架构,ARM公司是ARM架构(大端和小端都支持,默认是小端模式)。其中PowerPC系列采用bigendian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是bigendian,什么又是little endian呢?
字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。基于X86平台的PC机是小端字节序的,而有的嵌入式平台则是大端字节序的。因而对int、uint16、uint32等多于1字节类型的数据,在这些嵌入式平台上应该变换其存储顺序。通常我们认为,在空中传输的字节的顺序即网络字节序为标准顺序,考虑到与协议的一致以及与同类其它平台产品的互通,在程序中发数据包时,将主机字节序转换为网络字节序,收数据包处将网络字节序转换为主机字节序。
    其实big endian是指低地址存放最高有效字节(MSB),而littleendian则是低地址存放最低有效字节(LSB)。 
    用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:
Big Endian
  低地址                                           高地址
  ----------------------------------------->
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     12        34      56        78    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
  低地址                                           高地址
  ----------------------------------------->
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     78        56      34        12    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用bigendian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取bigendian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。
    无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把bigendian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。ANSIC中提供了下面四个转换字节序的宏。

测试大小端一般使用union的特性。union是一个联合体,所有变量公用一块内存,只是在不同的时候解释不同。其在内存中存储是按最长的那个变量所需要的位数来开辟内存的。

       代码如下:     

    #include <iostream>      using namespace std;      union       {          int number;          char s;      }test;      bool testBigEndin()      {          test.number=0x01000002;          return (test.s==0x01);      }      void main()      {          if (testBigEndin())                cout<<"big"<<endl;          else               cout<<"small"<<endl;          }  

    其中union的实际内存长度是int,即一个字,在32位机上是32位。而char是一个byte,只会取第一个低地址字节。所以他的值可以用来判断大小端。

0 0
原创粉丝点击