概述:

大端模式和小端模式是说一个数据在内存中存储的顺序问题,如果低位存放在高位内存中,叫做小端存储,反之叫做小端存储。在涉及到一些底层操作,或者是网络编程的时候,经常会碰到这个问题,也是面试中经常会用到的问题。:-)

 

重要性:

大端和小端字节序的问题在网络中以及在不同的操作系统的兼容性中是一个比较大的问题。它关系到不同操作系统和网络传输是否能够保证数据的语义正确性。

 

大端模式与小端模式

一、概念及详解

 

Byte Endian是指字节在内存中的组织,所以也称它为Byte Ordering,或Byte Order。 对于数据中跨越多个字节的对象, 我们必须为它建立这样的约定:
(1) 它的地址是多少?
(2) 它的字节在内存中是如何组织的?
 
针对第一个问题,有这样的解释:
 对于跨越多个字节的对象,一般它所占的字节都是连续的,它的地址等于它所占字节最低地址。(链表可能是个例外, 但链表的地址可看作链表头的地址)。
 
 比如: int x, 它的地址为0×100。 那么它占据了内存中的Ox100, 0×101, 0×102, 0×103这四个字节(32位系统,所以int占用4个字节)。
 
上面只是内存字节组织的一种情况: 多字节对象在内存中的组织有一般有两种约定。 考虑一个W位的整数。
 
 它的各位表达如下:[Xw-1, Xw-2, ... , X1, X0],它的
    MSB (Most Significant Byte, 最高有效字节)为 [Xw-1, Xw-2, ... Xw-8];
    LSB (Least Significant Byte, 最低有效字节)为 [X7,X6,..., X0]。 
    其余的字节位于MSB, LSB之间。
 
LSB和MSB谁位于内存的最低地址, 即谁代表该对象的地址? 
这就引出了大端(Big Endian)与小端(Little Endian)的问题。
如果LSB在MSB前面, 既LSB是低地址, 则该机器是小端; 反之则是大端。

 

  big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。
         用文字说明可能比较抽象,下面用图像加以说明。比如数字0×12345678在两种不同字节序CPU中的存储顺序如下所示:

Big Endian

   低地址                                            高地址
   —————————————–>
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     12     |      34    |     56      |     78    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Little Endian

   低地址                                            高地址
   —————————————–>
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     78     |      56    |     34      |     12    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

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

 

 在各种体系的计算机中通常采用的字节存储机制主要有两种: big-endian和little-endian,即大端模式和小端模式。
   先回顾两个关键词,MSB和LSB:
   MSB:Most Significant Bit ——- 最高有效位
        LSB:Least Significant Bit ——- 最低有效位
   大端模式(big-edian)
   big-endian:MSB存放在最低端的地址上。
   举例,双字节数0×1234以big-endian的方式存在起始地址0×00002000中:
        | data | <– address
        | 0×12 | <– 0×00002000
        | 0×34 | <– 0×00002001
   在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为例):
        bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
        ——MSB———————————-LSB
        val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
        +——————————————–+
        = 0×8 B 8 A
   小端模式(little-endian)
   little-endian:LSB存放在最低端的地址上。
   举例,双字节数0×1234以little-endian的方式存在起始地址0×00002000中:
| data |<– address
        | 0×34 | <– 0×00002000
        | 0×12 | <– 0×00002001
   在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如下(以双字节数0x8B8A为例):
bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
        ——MSB———————————–LSB
        val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
        +———————————————+
        = 0×8 B 8 A

 

二、数组在大端小端情况下的存储:
以unsigned int value = 0×12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下:
高地址
—————
buf[3] (0×78) — 低位
buf[2] (0×56)
buf[1] (0×34)
buf[0] (0×12) — 高位
—————
低地址
Little-Endian: 低地址存放低位,如下:
高地址
—————
buf[3] (0×12) — 高位
buf[2] (0×34)
buf[1] (0×56)
buf[0] (0×78) — 低位
————–
低地址

 

三、大端小端转换方法:
   Big-Endian转换成Little-Endian如下:
#define BigtoLittle16(A)                 ((((uint16)(A) & 0xff00) >> 8) | \
                                                          (((uint16)(A) & 0x00ff) << 8))
#define BigtoLittle32(A)                 ((((uint32)(A) & 0xff000000) >> 24) | \
                                                          (((uint32)(A) & 0x00ff0000) >> 8) | \
                                                          (((uint32)(A) & 0x0000ff00) << 8) | \
                                                          (((uint32)(A) & 0x000000ff) << 24))

转换程序:

 

 

四、大端小端检测方法:
   如何检查处理器是big-endian还是little-endian?
   联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big- endian模式读写。
int checkCPUendian()
{
union
{
unsigned int a;
unsigned char b;
}c;
c.a = 1;
return (c.b == 1);
}
/*return 1 : little-endian, return 0:big-endian*/

 

另外的方法:

 

bool IsBig_Endian()
//如果字节序为big-endian,返回true;
//反之为   little-endian,返回false
{
    unsigned short test = 0×1122;
    if(*( (unsigned char*) &test ) == 0×11)
       return TRUE;
else
    return FALSE;

}//IsBig_Endian()

相关文章推荐

,
Trackback

only 1 comment untill now

  1. [...] « 大端模式与小端模式的概念/应用和转换 [...]

Add your comment now