转:大端序与小端序

总结:

内存中地址始终是低端地址在前,高端地址在后。 这里高低端按内存地址大小算。小地址就是低端。

如:byte数组,0001 0002 0003 0004  这个就是小地址在前。

大端序: 数据字节,从左到右 是  高位到低位。 所以大端序是,高位字节(最左就是最高位),放在地址低端 ,按人类习惯,左边到右边按顺序放入内存地址。

小端序: 数据字节,从左到右 是  高位到低位。 所以小端序是,高位字节(最左就是最高位),放在地址高端,按计算机存储(这里跟处理器有关下面有解释)从数据低位字节开始存储,放入低端地址中(也就是最左地址)

例子:

 /**
   * int转byte[] 高位在前,大端字符序
   */
  public static byte[] intToBytes(int value) {
    byte[] bytes = new byte[4];
    bytes[0] = (byte) (value >> 24);
    bytes[1] = (byte) (value >> 16);
    bytes[2] = (byte) (value >> 8);
    bytes[3] = (byte) (value >> 0);
    return bytes;
  }
  /**
   * int转byte[] 高位在后,小端字符序
   */
  public static byte[] intToBytes(int value) {
    byte[] bytes = new byte[4];
    bytes[3] = (byte) (value >> 24);
    bytes[2] = (byte) (value >> 16);
    bytes[1] = (byte) (value >> 8);
    bytes[0] = (byte) (value >> 0);
    return bytes;
  }

 

点击进入原地址

何为大端序,小端序?

简单点说,就是字节的存储顺序,如果数据都是单字节的,那怎么存储无所谓了,但是对于多字节数据,比如int,double等,就要考虑存储的顺序了。注意字节序是硬件层面的东西,对于软件来说通常是透明的。再说白一点,字节序通常只和你使用的处理器架构有关,而和编程语言无关,比如常见的Intel x86系列就是小端序。

Big-endian(大端序)

数据的高位字节存放在地址的低端 低位字节存放在地址高端

Little-endian(小端序)

数据的高位字节存放在地址的高端 低位字节存放在地址低端

字节的高位与低位
举个例子,int a = 0x12345678 ; 那么左边12就是高位字节,右边的78就是低位字节,从左到右,由高到低,(注意,高低乃相对而言,比如56相对于78是高字节,相对于34是低字节)

地址的高端与低端
0x00000001
0x00000002
0x00000003
0x00000004
从上倒下,由低到高,地址值小的为低端,地址值大的为高端。

不同字节序如何存储数据?

看看两种方式如何存储数据,假设从地址0x00000001处开始存储十六进制数0x12345678,那么

Bit-endian 如此存放(按原来顺序存储)
0x00000001           -- 12
0x00000002           -- 34
0x00000003           -- 56
0x00000004           -- 78

Little-endian 如此存放(颠倒顺序储存)
0x00000001           -- 78
0x00000002           -- 56
0x00000003           -- 34
0x00000004           -- 12

一个很好的记忆方法是,大端序是按照数字的书写顺序进行存储的,而小端序是颠倒书写顺序进行存储的。

编程判断大端序和小端序

方法一

bool IsBigEndian()
{
    int a =1 ; 
    if(((char*)&a)[3] ==1)
        return true ;
    else
        return false ;
}

打开VS的内存窗口,看一下a的存储方式,一目了然

转:大端序与小端序_第1张图片

由于a是int,所以占四个字节,其值是00000001,存储方式如下。所以a[3]是0,不是大端序。一个更标准的写法是将a[3]替换为a[sizeof(int) - 1]。

0x0012FE88  01

0x0012FE89  00

0x0012FE8A  00

0x0012FE8B  00

方法二,使用union,原理见后面的面试题。

bool IsBigEndian()
{
    union
    {
        unsigned short a ;
        char b ;
    } c;

    c.a =0x0102 ;

    if(c.b ==1)
        return true ;
    else
        return false ;
}

一道面试题

来道题巩固一下,下面代码输出什么?

union u
{
    int i ;
    char x[2] ;
} a ;

int main(void)
{
    a.x[0] ='1' ;
    a.x[1] ='2' ;

    cout << a.i << endl ;

    getchar() ;
    return 0 ;
}

这个题,要看你使用的是什么系列的CPU,姑且假设是Intel系列的。Union是一个特殊的结构,其中所有成员共享结一个内存地址,任意时间只能存储一个成员,上面的Union大小为4个字节,所以上面的代码存储完字符1和2之后,Union的存储貌似应该是0x31320000,31和32分别是字符'1'和'2'的十六进制ASCII码(注意是字符1和2,而不是整数),但是Intel系列的CPU都是按照小端序存储的,所以,正确的顺序是0x00003231,对应的十进制数是12849,你答对了么?

关于字节序的详细内容,请看Wikipedia的介绍 http://en.wikipedia.org/wiki/Endianness

== Happy coding ==

The End

你可能感兴趣的:(数据结构学习篇)