大端字节序和小端字节序问题(big-endian & little-endian)

转载来源: http://hi.baidu.com/michael1517/blog/item/12ff4dd3a5478d2e960a1631.html 

 

      谈到字节序的问题,必然牵涉到两大CPU派系。那就是MotorolaPowerPC系列CPUIntelx86系列CPUPowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?

      简单地说,big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。

        所谓的大端模式(Big-endian),是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
        所谓的小端模式(Little-endian),是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
       为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模 式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
        用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:  

Big Endian

 

   低地址                                            高地址

  ----------------------------------------------------------------------------->

  |    12    |     34   |    56     |    78   |

 

Little Endian

 

   低地址                                            高地址

  ----------------------------------------------------------------------------->

  |    78    |     56   |    34     |    12   |

 

     从上面两图可以看出,采用big endian方式存储数据是符合我们人类的思维习惯的。

     为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?尤其是当你把你在微机上运算的结果运用到计算机群上去的话。

在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。

所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。ANSI C中提供了下面四个转换字节序的宏。


一道C语言的试题:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1

解答:

int checkCPU()
{
 
{
  
union w
  
{
   
int a;
   
char b;
  
} c;
  
c.a = 1;
  
return (c.b == 1);
 
}
}

 

嵌入式系统开发者应该对Little-endianBig-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234Little- endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址

存放内容

0x4000

0x34

0x4001

0x12


  而在Big-endian模式CPU内存中的存放方式则为:

内存地址

存放内容

0x4000

0x12

0x4001

0x34


  32bit宽的数0x12345678Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址

存放内容

0x4000

0x78

0x4001

0x56

0x4002

0x34

0x4003

0x12


  而在Big-endian模式CPU内存中的存放方式则为:

内存地址

存放内容

0x4000

0x12

0x4001

0x34

0x4002

0x56

0x4003

0x78


  联合体union的存放顺序是所有成员都从低地址开始存放,解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值