• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            大端小端(Big- Endian和Little-Endian)

            1/ 網(wǎng)絡(luò)字節(jié)順序是TCP/IP中規(guī)定好的一種數(shù)據(jù)表示格式,它與具體的CPU類型、操作系統(tǒng)等無(wú)關(guān),從而可以保證數(shù)據(jù)在不同主機(jī)之間傳輸時(shí)能夠被正確解釋,網(wǎng)絡(luò)字節(jié)順序采用big-endian排序方式。
            2/ 而我們常用的 x86 CPU (intel, AMD) 電腦是 little-endian,也就是整數(shù)的低位字節(jié)放在內(nèi)存的低字節(jié)處。

            舉個(gè)例子吧。假定你的數(shù)據(jù)是0x1234,
            在網(wǎng)絡(luò)字節(jié)順序里 這個(gè)數(shù)據(jù)放到內(nèi)存中就應(yīng)該顯示成
            addr addr+1
            0x12 0x34
            而在x86電腦上,數(shù)據(jù)0x1234放到內(nèi)存中實(shí)際是:
            addr addr+1
            0x34 0x12
            htons 的用處就是把實(shí)際主機(jī)內(nèi)存中的整數(shù)存放方式調(diào)整成網(wǎng)絡(luò)字節(jié)順序。


            ------------------------------------------------------------------------------------------------------------

            大端小端(Big- Endian和Little-Endian)

            字節(jié)序(Endian),大端(Big-Endian),小端(Little-Endian) 圖文并茂

            http://m.shnenglu.com/tx7do/archive/2009/01/06/71276.html

             http://my.oschina.net/alphajay/blog/5478

            在 各種計(jì)算機(jī)體系結(jié)構(gòu)中,對(duì)于字節(jié)、字等的存儲(chǔ)機(jī)制有所不同,因而引發(fā)了計(jì)算機(jī) 通信領(lǐng) 域中一個(gè)很重要的問(wèn)題,即通信雙方交流的信息單元(比特、字節(jié)、字、雙字等等)應(yīng)該以什么樣的順序進(jìn)行傳送。如果不達(dá)成一致的規(guī)則,通信雙方將無(wú)法進(jìn)行正 確的編/譯碼從而導(dǎo)致通信失敗。目前在各種體系的計(jì)算機(jī)中通常采用的字節(jié)存儲(chǔ)機(jī)制主要有兩種:Big-Endian和Little-Endian,下面先 從字節(jié)序說(shuō)起。

             

            一、什么是字節(jié)序

            字節(jié)序,顧名思義字節(jié)的順序,再多說(shuō)兩句就是大于一個(gè)字節(jié)類型的數(shù)據(jù)在內(nèi)存中的存放順序(一個(gè)字節(jié)的數(shù)據(jù)當(dāng)然就無(wú)需談順序的問(wèn)題了)其實(shí)大部分人在實(shí)際的開(kāi) 發(fā)中都很少會(huì)直接和字節(jié)序打交道。唯有在跨平臺(tái)以及網(wǎng)絡(luò)程序中字節(jié)序才是一個(gè)應(yīng)該被考慮的問(wèn)題。

            在所有的介紹字節(jié)序的文章中都會(huì)提到字 節(jié)序分為兩類:Big-Endian和Little-Endian,引用標(biāo)準(zhǔn)的Big-Endian和Little-Endian的定義如下:
            a) Little-Endian就是低位字節(jié)排放在內(nèi)存的低地址端,高位字節(jié)排放在內(nèi)存的高地址端
            b) Big-Endian就是高位字節(jié)排放在內(nèi)存的低地址端,低位字節(jié)排放在內(nèi)存的高地址端
            c) 網(wǎng)絡(luò)字節(jié)序:TCP/IP各層協(xié)議將字節(jié)序定義為Big-Endian,因此TCP/IP協(xié)議中使用的字節(jié)序通常稱之為網(wǎng)絡(luò)字節(jié)序。

            1.1 什么是高/低地址端

            首先我們要知道我們C程序映像中內(nèi)存的空間布局情況:在《C專 家編程》中或者《Unix環(huán)境高級(jí)編程》中有關(guān)于內(nèi)存空間布局情況的說(shuō)明,大致如下圖:
            ----------------------- 最高內(nèi)存地址 0xffffffff
            棧底

            棧頂

            -----------------------

            NULL (空洞)
            -----------------------

            -----------------------
            未初始 化的數(shù)據(jù)
            ----------------------- 統(tǒng)稱數(shù)據(jù)段
            初始化的數(shù)據(jù)
            -----------------------
            正 文段(代碼段)
            ----------------------- 最低內(nèi)存地址 0x00000000

            以上圖為例如果我們?cè)跅?上分配一個(gè)unsigned char buf[4],那么這個(gè)數(shù)組變量在棧上是如何布局的呢?看下圖:
            棧底 (高地址)
            ----------
            buf[3]
            buf[2]
            buf[1]
            buf[0]

            ----------
            棧頂 (低地址)

            1.2 什么是高/低字節(jié)

            現(xiàn)在我們弄清了高/低地址,接著考慮高/低字節(jié)。有些文章中稱低位字節(jié)為最低有效位,高位字節(jié)為最高有效位。如果我們有一個(gè)32位無(wú)符號(hào)整型0x12345678,那么高位是什么,低位又是什么呢? 其實(shí)很簡(jiǎn)單。在十進(jìn)制中我們都說(shuō)靠左邊的是高位,靠右邊的是低位,在其他進(jìn)制也是如此。就拿 0x12345678來(lái)說(shuō),從高位到低位的字節(jié)依次是0x12、0x34、0x56和0x78
            高/低地址端和高/低字節(jié)都弄清了。我們?cè)賮?lái)回顧 一下Big-Endian和Little-Endian的定義,并用圖示說(shuō)明兩種字節(jié)序:
            以u(píng)nsigned int value = 0x12345678為例,分別看看在兩種字節(jié)序下其存儲(chǔ)情況,我們可以用unsigned char buf[4]來(lái)表示value:

            Big-Endian: 低地址存放高位,如下圖:
            棧底 (高地址)
            ---------------
            buf[3] (0x78) -- 低位
            buf[2] (0x56)
            buf[1] (0x34)
            buf[0] (0x12) -- 高位
            ---------------
            棧頂 (低地址)

            Little-Endian: 低地址存放低位,如下圖:
            棧底 (高地址)
            ---------------
            buf[3] (0x12) -- 高位
            buf[2] (0x34)
            buf[1] (0x56)
            buf[0] (0x78) -- 低位
            --------------
            棧 頂 (低地址)

             

            二、各種Endian

            2.1 Big-Endian

            計(jì)算機(jī)體系結(jié)構(gòu)中一種描述多字節(jié)存儲(chǔ)順序的術(shù)語(yǔ),在這種機(jī)制中最重要字節(jié)(MSB)存放在最低端的地址 上。采用這種機(jī)制的處理器有IBM3700系列、PDP-10、Mortolora微處理器系列和絕大多數(shù)的RISC處理器。
            +----------+
            | 0x34 |<-- 0x00000021
            +----------+
            | 0x12 |<-- 0x00000020
            +----------+
            圖 1:雙字節(jié)數(shù)0x1234以Big-Endian的方式存在起始地址0x00000020中

             在Big-Endian中,對(duì)于bit序列 中的序號(hào)編排方式如下(以雙字節(jié)數(shù)0x8B8A為例):
            bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
            +-----------------------------------------+
            val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
            +----------------------------------------+
            圖 2:Big-Endian的bit序列編碼方式

            2.2 Little-Endian

            計(jì)算機(jī)體系結(jié)構(gòu)中 一種描述多字節(jié)存儲(chǔ)順序的術(shù)語(yǔ),在這種機(jī)制中最不重要字節(jié)(LSB)存放在最低端的地址上。采用這種機(jī)制的處理器有PDP-11、VAX、Intel系列 微處理器和一些網(wǎng)絡(luò)通信設(shè)備。該術(shù)語(yǔ)除了描述多字節(jié)存儲(chǔ)順序外還常常用來(lái)描述一個(gè)字節(jié)中各個(gè)比特的排放次序。

            +----------+
            | 0x12 |<-- 0x00000021
            +----------+
            | 0x34 |<-- 0x00000020
            +----------+

            圖3:雙字節(jié)數(shù)0x1234以Little-Endian的方式存在起始地址0x00000020中

             在 Little-Endian中,對(duì)于bit序列中的序號(hào)編排和Big-Endian剛好相反,其方式如下(以雙字節(jié)數(shù)0x8B8A為例):

            bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
            +-----------------------------------------+
            val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
            +-----------------------------------------+
            圖 4:Little-Endian的bit序列編碼方式

            注2:通常我們說(shuō)的主機(jī)序(Host Order)就是遵循Little-Endian規(guī)則。所以當(dāng)兩臺(tái)主機(jī)之間要通過(guò)TCP/IP協(xié)議進(jìn)行通信的時(shí)候就需要調(diào)用相應(yīng)的函數(shù)進(jìn)行主機(jī)序 (Little-Endian)和網(wǎng)絡(luò)序(Big-Endian)的轉(zhuǎn)換

            注3:正因?yàn)檫@兩種機(jī)制對(duì)于同一bit序列的序號(hào)編排方式恰 恰相反,所以《現(xiàn)代英漢詞典》中對(duì)MSB的翻譯為“最高有效位”欠妥,故本文定義為“最重要的bit/byte”。

            2.3 Middle-Endian

            除了Big-Endian和Little-Endian之外的多字節(jié)存儲(chǔ)順序就是Middle- Endian,比如以4個(gè)字節(jié)為例:象以3-4-1-2或者2-1-4-3這樣的順序存儲(chǔ)的就是Middle-Endian。這種存儲(chǔ)順序偶爾會(huì)在一些小 型機(jī)體系中的十進(jìn)制數(shù)的壓縮格式中出現(xiàn)

            嵌入式系統(tǒng)開(kāi)發(fā)者應(yīng)該對(duì)Little-endian和Big-endian模式非常了解。采用 Little-endian模式的CPU對(duì)操作數(shù)的存放方式是從低字節(jié)到高字節(jié),而Big-endian模式對(duì)操作數(shù)的存放方式是從高字節(jié)到低字節(jié)。 32bit寬的數(shù)0x12345678在Little-endian模式CPU內(nèi)存中的存放方式(假設(shè)從地址0x4000開(kāi)始存放)為:

            內(nèi)存 地址 0x4000 0x4001 0x4002 0x4003
            存放內(nèi)容 0x78 0x56 0x34 0x12

             

            而在Big- endian模式CPU內(nèi)存中的存放方式則為:

            內(nèi)存地址 0x4000 0x4001 0x4002 0x4003
            存放內(nèi)容 0x12 0x34 0x56 0x78

             

            三、Big-EndianLittle-Endian優(yōu)缺點(diǎn)

            Big-Endian優(yōu)點(diǎn):靠首先提取高位字節(jié),你總是可以由看看在偏移位置為0的字節(jié)來(lái)確定這個(gè)數(shù)字是 正數(shù)還是負(fù)數(shù)。你不必知道這個(gè)數(shù)值有多長(zhǎng),或者你也不必過(guò)一些字節(jié)來(lái)看這個(gè)數(shù)值是否含有符號(hào)位這個(gè)數(shù)值是以它們被打印出來(lái)的順序存放的,所以從二進(jìn)制到十進(jìn)制的函數(shù)特別有效。因而,對(duì)于不同要求的機(jī)器,在設(shè)計(jì)存取方式時(shí)就會(huì)不同。

            Little-Endian優(yōu)點(diǎn):提取一個(gè),兩個(gè),四個(gè)或者更長(zhǎng)字節(jié)數(shù)據(jù)的匯編指令以與其他所有格式相同的方式進(jìn)行:首先在偏移地址為0的地方提取最低位的字節(jié),因?yàn)榈刂菲坪妥止?jié)數(shù)是一對(duì) 一的關(guān)系,多重精度的數(shù)學(xué)函數(shù)就相對(duì)地容易寫(xiě)了

            如 果你增加數(shù)字的值,你可能在左邊增加數(shù)字(高位非指數(shù)函數(shù)需要更多的數(shù)字)。 因此, 經(jīng)常需要增加兩位數(shù)字并移動(dòng)存儲(chǔ)器里所有Big-endian順序的數(shù)字,把所有數(shù)向右移,這會(huì)增加計(jì)算機(jī)的工作量。不過(guò),使用Little- Endian的存儲(chǔ)器中不重要的字節(jié)可以存在它原來(lái)的位置,新的數(shù)可以存在它的右邊的高位地址里。這就意味著計(jì)算機(jī)中的某些計(jì)算可以變得更加簡(jiǎn)單和快速。

            四、如何檢查處理器是Big-Endian還是Little-Endian?

            由于聯(lián)合體union的存放順序是所有成員都從低地址開(kāi)始存放,利用該特性就可以輕松地獲得了CPU對(duì)內(nèi)存采用Little- endian還是Big-endian模式讀寫(xiě)。例如:
            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*/

             

            五、Big-EndianLittle-Endian轉(zhuǎn) 換

             

            現(xiàn)有的平臺(tái)上Intel的X86采用的是Little-Endian,而像 Sun的SPARC采用的就是Big-Endian。那么在跨平臺(tái)或網(wǎng)絡(luò)程序中如何實(shí)現(xiàn)字節(jié)序的轉(zhuǎn)換呢?這個(gè)通過(guò)C語(yǔ)言的移位操作很容易實(shí)現(xiàn),例如下面的 宏:

            #if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)

            #define htons(A)   (A)
            #define htonl(A)     (A)
            #define ntohs(A)   (A)
            #define ntohl(A)    (A)

            #elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)

            #define htons(A)     ((((uint16)(A) & 0xff00) >> 8) | \
            (((uint16)(A) & 0x00ff) << 8))
            #define htonl(A)     ((((uint32)(A) & 0xff000000) >> 24) | \
            (((uint32)(A) & 0x00ff0000) >> 8) | \
            (((uint32)(A) & 0x0000ff00) << 8) | \
            (((uint32)(A) & 0x000000ff) << 24))
            #define ntohs htons
            #define ntohl htohl

            #else

            #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."

             

             

            網(wǎng)絡(luò)字節(jié)順序
            1、字節(jié)內(nèi)的比特位不受這種順序的影響
            比如一個(gè)字節(jié) 1000 0000 (或表示為十六進(jìn)制 80H)不管是什么順序其內(nèi)存中的表示法都是這樣。

             

            2、大于1個(gè)字節(jié)的數(shù)據(jù)類型才有字節(jié)順序問(wèn)題
            比如 Byte A,這個(gè)變量只有一個(gè)字節(jié)的長(zhǎng)度,所以根據(jù)上一條沒(méi)有字節(jié)順序問(wèn)題。所以字節(jié)順序是“字節(jié)之間的相對(duì)順序”的意思。


            3、大于1個(gè)字節(jié)的數(shù)據(jù)類型的字節(jié)順序有兩種
            比如 short B,這是一個(gè)兩字節(jié)的數(shù)據(jù)類型,這時(shí)就有字節(jié)之間的相對(duì)順序問(wèn)題了。
            網(wǎng)絡(luò)字節(jié)順序是“所見(jiàn)即所得”的順序。而Intel類型的CPU的字節(jié)順序與此相反。
            比如上面的 short B=0102H(十六進(jìn)制,每?jī)晌槐硎疽粋€(gè)字節(jié)的寬度)。所見(jiàn)到的是“0102”,按一般數(shù)學(xué)常識(shí),數(shù)軸從左到右的方向增加,即內(nèi)存地址從左到右增加的話,在內(nèi)存中這個(gè) short B的字節(jié)順序是:
            01 02
            這就是網(wǎng)絡(luò)字節(jié)順序。所見(jiàn)到的順序和在內(nèi)存中的順序是一致的!
            假設(shè)通過(guò)抓包得到網(wǎng)絡(luò)數(shù)據(jù)的兩個(gè)字節(jié)流為:01 02

            而相反的字節(jié)順序就不同了,其在內(nèi)存中的順序?yàn)椋?2 01

            如果這表示兩個(gè) Byte類型的變量,那么自然不需要考慮字節(jié)順序的問(wèn)題。如果這表示一個(gè) short 變量,那么就需要考慮字節(jié)順序問(wèn)題。根據(jù)網(wǎng)絡(luò)字節(jié)順序“所見(jiàn)即所得”的規(guī)則,這個(gè)變量的值就是:0102

            假設(shè)本地主機(jī)是Intel類型的,那么要表示這個(gè)變量,有點(diǎn)麻煩:
            定義變量 short X,字節(jié)流地址為:pt,按順序讀取內(nèi)存是為x=*((short*)pt);
            那么X的內(nèi)存順序當(dāng)然是 01 02按非“所見(jiàn)即所得”的規(guī)則,這個(gè)內(nèi)存順序和看到的一樣顯然是不對(duì)的,所以要把這兩個(gè)字節(jié)的位置調(diào)換。調(diào)換的方法可以自己定義,但用已經(jīng)有的API還是更為方便。

            網(wǎng)絡(luò)字節(jié)順序與主機(jī)字節(jié)順序
            NBO 與HBO 網(wǎng)絡(luò)字節(jié)順序NBO(Network Byte Order):按從高到低的順序存儲(chǔ),在網(wǎng)絡(luò)上使用統(tǒng)一的網(wǎng)絡(luò)字節(jié)順序,可以避免兼容性問(wèn)題。主機(jī)字節(jié)順序(HBO,Host Byte Order):不同的機(jī)器HBO不相同,與CPU設(shè)計(jì)有關(guān)計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,所以對(duì)于在內(nèi)部是以低位字節(jié)優(yōu)先方式存儲(chǔ)數(shù)據(jù)的機(jī)器,在Internet上傳輸數(shù)據(jù)時(shí)就需要進(jìn)行轉(zhuǎn)換。

            htonl()
            簡(jiǎn)述:
                將主機(jī)的無(wú)符號(hào)長(zhǎng)整形數(shù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。
                #include <winsock.h>
                u_long PASCAL FAR htonl( u_long hostlong);
                hostlong:主機(jī)字節(jié)順序表達(dá)的32位數(shù)。
            注釋:
                本函數(shù)將一個(gè)32位數(shù)從主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。
            返回值:
                htonl()返回一個(gè)網(wǎng)絡(luò)字節(jié)順序的值。

            inet_ntoa()
            簡(jiǎn)述:
            將網(wǎng)絡(luò)地址轉(zhuǎn)換成“.”點(diǎn)隔的字符串格式。
            #include <winsock.h>
            char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
            in:一個(gè)表示Internet主機(jī)地址的結(jié)構(gòu)。
            注釋:
            本 函數(shù)將一個(gè)用in參數(shù)所表示的Internet地址結(jié)構(gòu)轉(zhuǎn)換成以“.” 間隔的諸如“a.b.c.d”的字符串形式。請(qǐng)注意inet_ntoa()返回的字符串存放在WINDOWS套接口實(shí)現(xiàn)所分配的內(nèi)存中。應(yīng)用程序不應(yīng)假設(shè) 該內(nèi)存是如何分配的。在同一個(gè)線程的下一個(gè)WINDOWS套接口調(diào)用前,數(shù)據(jù)將保證是有效。
            返回值:
            若無(wú)錯(cuò)誤發(fā)生,inet_ntoa()返回一個(gè)字符指針。否則的話,返回NULL。其中的數(shù)據(jù)應(yīng)在下一個(gè)WINDOWS套接口調(diào)用前復(fù)制出來(lái)。

            網(wǎng) 絡(luò)中傳輸?shù)臄?shù)據(jù)有的和本地字節(jié)存儲(chǔ)順序一致,而有的則截然不同,為了數(shù)據(jù)的一致性,就要把本地的數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)上使用的格式,然后發(fā)送出去,接收的時(shí)候也 是一樣的,經(jīng)過(guò)轉(zhuǎn)換然后才去使用這些數(shù)據(jù),基本的庫(kù)函數(shù)中提供了這樣的可以進(jìn)行字節(jié)轉(zhuǎn)換的函數(shù),如和htons( ) htonl( ) ntohs( ) ntohl( ),這里n表示network,h表示host,htons( ) htonl( )用于本地字節(jié)向網(wǎng)絡(luò)字節(jié)轉(zhuǎn)換的場(chǎng)合,s表示short,即對(duì)2字節(jié)操作,l表示long即對(duì)4字節(jié)操作。同樣ntohs( )ntohl( )用于網(wǎng)絡(luò)字節(jié)向本地格式轉(zhuǎn)換的場(chǎng)合。

             #endif

            posted on 2012-05-17 10:13 多彩人生 閱讀(3195) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久国产精品二国产精品| 久久人妻少妇嫩草AV蜜桃| 久久精品国产第一区二区三区| 九九精品99久久久香蕉| 2020最新久久久视精品爱| 久久夜色撩人精品国产| 99久久精品午夜一区二区| 日本精品久久久久影院日本| 色欲av伊人久久大香线蕉影院| 欧美亚洲国产精品久久蜜芽| yy6080久久| 久久精品国产一区二区三区| 久久国产精品77777| 婷婷久久五月天| 久久精品国产亚洲5555| 国产精品一区二区久久不卡| 亚洲国产成人久久一区WWW| 蜜桃麻豆www久久| 99久久人妻无码精品系列| 日韩精品久久久久久久电影| 99久久精品无码一区二区毛片| 日韩人妻无码精品久久久不卡 | 久久久久亚洲av毛片大| 久久精品人人做人人爽97| 久久亚洲AV无码精品色午夜麻豆| 精品综合久久久久久88小说 | 精品久久久久久国产三级 | 久久免费视频6| 国产精品久久久久一区二区三区| 韩国无遮挡三级久久| 久久久久久夜精品精品免费啦| 久久久久久精品久久久久| 亚洲欧美国产日韩综合久久| 久久久久综合中文字幕| 久久国产精品免费| 久久99精品久久久久久水蜜桃| 久久99国产精品久久99果冻传媒| 久久精品国产99久久久| 999久久久免费精品国产| 国产精品久久久久9999高清| 精品久久久久久成人AV|