美文网首页
Big Endian与Little Endian字节存储顺序

Big Endian与Little Endian字节存储顺序

作者: 蜗牛Michael | 来源:发表于2019-12-22 19:24 被阅读0次

    不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序。分为小端格式和大端格式(Little-Endian&Big-Endian):

    1. Little-endian:将低位字节存储在起始地址(低位编址)
    2. Big-endian:将高位字节存储在起始地址(高位编址)

    比如0x1234; 低8位是34,高8位是12;如果它们分配的内存其实地址是0x0001,
    那么如果是大端存储,那么0x0001内存低位地址存放高位字节12;如果是小端存储,那么0x0001内存低位地址存放低位字节34,0x0002存放12。

    一、历史由来

    据Jargon File记载,endian这个词来源于Jonathan Swift在1726年写的讽刺小说 "Gulliver's Travels"(《格利佛游记》)。该小说在描述Gulliver畅游小人国时碰到了如下的一个场景。在小人国里的小人因为非常小(身高6英寸)所以总是碰到一些意想不到的问题。有一次因为对水煮蛋该从大的一端(Big-End)剥开还是小的一端(Little-End)剥开的争论而引发了一场战争,并形成了两支截然对立的队伍:支持从大的一端剥开的人Swift就称作Big-Endians,而支持从小的一端剥开的人就称作Little-Endians......(后缀ian表明的就是支持某种观点的人)。

    1980年,Danny Cohen在其著名的论文"On Holy Wars and a Plea for Peace"中为了平息一场关于在消息中字节该以什么样的顺序进行传送的争论而引用了该词。该文中,Cohen非常形象贴切地把支持从一个消息序列的最高位开始传送的那伙人叫做Big-Endians,支持从最低位开始传送的相对应地叫做Little-Endians。此后Endian这个词便随着这篇论文而被广为采用。

    二、深入理解

    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.

    三、背景MSB/LSB

    比如: int x, 它的地址为0x100。 那么它占据了内存中的Ox100, 0x101, 0x102, 0x103这四个字节(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之间。

    这就引出了大端(Big Endian)与小端(Little Endian)的问题。如果LSB在MSB前面, 既LSB是低地址, 则该机器是小端; 反之则是大端。

    对于数据中跨越多个字节的对象, 我们必须为它建立这样的约定:

    1. 它的地址是多少?
    2. 它的字节在内存中是如何组织的?

    对于跨越多个字节的对象,一般它所占的字节都是连续的,它的地址等于它所占字节最低地址。(链表可能是个例外, 但链表的地址可看作链表头的地址)。

    程序判断大端还是小端

    1. C/C++
    bool IsBig_Endian()
    //如果字节序为big-endian,返回true;
    //反之为   little-endian,返回false
    {
        unsigned short test = 0x1122;
        if(*( (unsigned char*) &test ) == 0x11)
           return TRUE;
    else
        return FALSE;
    }//IsBig_Endian()
    
    #include <stdio.h>
    
    int main()
    {
        union ut{
            short s;
            char c[2];
        }u;
        
        if(sizeof(short) == 2)
        {
            u.s = 0x0102;
            if(u.c[0] == 1 && u.c[1] == 2)
            {
                printf("big enidan.\n");
            } else if(u.c[0] == 2 && u.c[1] == 1)
            {
                printf("little endian.\n");
            }
        }
        return 0;
    }
    
    1. Java接口

    import java.nio.ByteOrder;

    if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
                    System.out.println("BIG_ENDIAN");
                } else {
                    System.out.println("LITTLE_ENDIAN");
                }
            }
    

    相关文章

      网友评论

          本文标题:Big Endian与Little Endian字节存储顺序

          本文链接:https://www.haomeiwen.com/subject/tyoonctx.html