新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM存儲格式之 大端小端

        ARM存儲格式之 大端小端

        作者: 時間:2016-11-11 來源:網絡 收藏
        開頭講個有關大端小端的故事:

          端模式(Endian)的這個詞出自Jonathan Swift書寫的《格列佛游記》。這本書根據將雞蛋敲開的方法不同將所有的人分為兩類,從圓頭開始將雞蛋敲開的人被歸為Big Endian,從尖頭開始將雞蛋敲開的人被歸為Littile Endian。小人國的內戰就源于吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。在計算機業Big Endian和Little Endian也幾乎引起一場戰爭。  

        本文引用地址:http://www.104case.com/article/201611/316677.htm

          我們知道在內存中數據是以字節為單位進行存儲的,每個地址單元對應著一個字節(byte),一個字節為8位(bite)。但是很多時候數據除了8bit額char外,還有16bit的short,32位的long型(要看具體的編譯器),必然存在多字節安排的問題。不同的計算機存放多字節值的順序不同,有些機器在起始地址存放低位字節(低位先存),即小端模式;有的機器在起始地址存放高位字節(高位先存),即大端模式。基于Intel的CPU,采用的是低位先存。而KEIL C51則為大端模式。大端小端對應著數據在存儲器中的存放順序。

          同時,在網絡傳輸中,網絡協議需要指定網絡字節順序,TCP/IP協議中使用16位整數和32位整數的高位先存模式,對應我們的大端模式。

          下面是兩個具體例子:

          16bit寬的數0x1234在Little-endian模式(以及Big-endian模式)CPU內存中的存放方式(假設從地址0x4000開始存放)為:

        內存地址小端模式存放內容大端模式存放內容
        0x40000x340x12
        0x40010x120x34

          32bit寬的數0x12345678在Little-endian模式以及Big-endian模式)CPU內存中的存放方式(假設從地址0x4000開始存放)為:

        內存地址小端模式存放內容大端模式存放內容
        0x40000x780x12
        0x40010x560x34
        0x40020x340x56
        0x40030x120x78

          聯合體union的存放順序是所有成員都從低地址開始存放,利用該特性可以輕松地獲得了CPU對內存采用Little-endian還是Big-endian模式讀寫。

          寫程序判斷處理器是Little-endian模式,還是Big-endian模式,可以通過以下程序:

          1>.通過將int強制類型轉換成char單字節,通過判斷起始存儲位置。

        1voidmain(intargc,char**argv)
        2{
        3inti=1;
        4char*cp=(char*)&i;//前面是指針運算符*,前值類型轉換。后面是取地址符號。
        5if(*cp)//如果此時cp指向的內存為1的話,則為小端,否則為大端。
        6printf("Little Endiann");
        7else
        8printf("Big Endiann");
        9
        10exit(EXIT_SUCCESS);
        11}

        注釋:如果小端方式中(i占至少兩個字節的長度)則i所分配的內存最小地址那個字節中就存著1,其他字節是0.大端的話則1在i的最高地址字節處存放,char是一個字節,所以強制將char型量p指向i則p指向的一定是i的最低地址,那么就可以判斷p中的值是不是1(或者為0,也即是假)來確定是不是小端。

        或者如下程序:

        voidmain()
        {
        shortintx;

        charx0,x1;

        x=0x1122;

        x0=((char*)&x)[0];//低地址單元
        x1=((char*)&x)[1];//高地址單元

        if(0x11==x0&&0x22==x1)
        {
        cout<<"Big_endian"<}
        else
        {
        cout<<"Little_endian"<}
        }

        2>.利用聯合體union的存放順序是所有成員都從低地址開始存放,判斷處理器模式。

        boolcheckCPU( )
        {
        {
        union w
        {
        inta;
        charb;

        } c;
        c.a=1;
        return(c.b==1);
        }
        }

        以及如下程序:

        boolisLittleEndian()
        {
        union _dword
        {
        intall;
        struct_bytes
        {
        charbyte0;
        charpad[3];
        }bytes;
        }dword;

        dword.all=0x87654321;

        return(0x21==dword.bytes.byte0);
        }

        分析:如果你的處理器調用函數isLittleEndian返回1,那么說明你的處理器為little endian,否則為big endian.注意,如果在little endian處理器上,byte0和pad按內存從低到高的存放順序:LOW->byte0 pad[0] pad[1] pad[2] ->HIGH;0x87654321按內存從低到高的存放順序: 0x21 0x43 0x65 0x87, 可見byte0對應到0x21。所以通過判斷dword中第一個字節dword.bytes.byte0是否與0x21相等就可以看出是否是little endian。

         PS:本文后面幾個程序都是從網上摘抄過來的,對于聯合體Union不是很清楚的可以參看http://blog.sina.com.cn/s/blog_3fa943920100ob37.html我覺得這篇博文寫的很詳細。通過本文對大端小端模式有了一個比較深的理解吧。也希望對讀者有些許幫助,謝謝!接下來我會總結下聯合Union結構和Struct的區別。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 化隆| 丹阳市| 正镶白旗| 东源县| 汨罗市| 阿拉善左旗| 双桥区| 繁昌县| 绵阳市| 马关县| 临汾市| 来安县| 讷河市| 镇江市| 安泽县| 青冈县| 泗水县| 怀宁县| 河曲县| 西吉县| 东兰县| 海盐县| 图木舒克市| 白河县| 桃源县| 彩票| 新邵县| 寿宁县| 商洛市| 温州市| 洱源县| 郎溪县| 巴塘县| 东光县| 渝中区| 海原县| 拜泉县| 砀山县| 东平县| 普定县| 安康市|