大端(Big_Endian)與小端(Little_Endian)詳解-_第1頁(yè)
大端(Big_Endian)與小端(Little_Endian)詳解-_第2頁(yè)
大端(Big_Endian)與小端(Little_Endian)詳解-_第3頁(yè)
大端(Big_Endian)與小端(Little_Endian)詳解-_第4頁(yè)
大端(Big_Endian)與小端(Little_Endian)詳解-_第5頁(yè)
已閱讀5頁(yè),還剩13頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、大端(Big_Endian)與小端(Little_Endian)詳解 -2011-05-15 17:23大端(Big_Endian)與小端(Little_Endian)詳解大端(Big Endian)與小端(Little Endian)簡(jiǎn)介/1. 你從哪里來?端模式(Endian)的這個(gè)詞出自Jonathan Swift書寫的格列佛游記。這本書根據(jù)將雞蛋敲開的方法不同將所有的人分為兩類,從圓頭開始將雞蛋敲開的人被歸為Big Endian,從尖頭開始將雞蛋敲開的人被歸為L(zhǎng)ittile Endian。小人國(guó)的內(nèi)戰(zhàn)就源于吃雞蛋時(shí)是究竟從大頭(Big-Endian)敲開還是從小頭(Little-End

2、ian)敲開。在計(jì)算機(jī)業(yè)Big Endian和Little Endian也幾乎引起一場(chǎng)戰(zhàn)爭(zhēng)。在計(jì)算機(jī)業(yè)界,Endian表示數(shù)據(jù)在存儲(chǔ)器中的存放順序。采用大端方式進(jìn)行數(shù)據(jù)存放符合人類的正常思維,而采用小端方式進(jìn)行數(shù)據(jù)存放利于計(jì)算機(jī)處理。下文舉例說明在計(jì)算機(jī)中大小端模式的區(qū)別。/2. 讀書百遍其義自見小端口訣: 高高低低 -> 高字節(jié)在高地址, 低字節(jié)在低地址大端口訣: 高低低高 -> 高字節(jié)在低地址, 低字節(jié)在高地址long test = 0x313233334;小端機(jī)器:低地址 ->高地址00000010: 34 33 32 31    

3、;     -> 4321大端機(jī)器:低地址 ->高地址00000010: 31 32 33 34         -> 4321test變量存儲(chǔ)的是的0x10這個(gè)地址, 那編譯器怎么知道是讀四個(gè)字節(jié)呢? -> 根據(jù)變量test的類型long可知這個(gè)變量占據(jù)4個(gè)字節(jié).那編譯器怎么讀出這個(gè)變量test所代表的值呢? -> 這就根據(jù)是little endian還是big endian來讀取所以, 小端, 其值為0x31323334; 大端, 其值為0x

4、34333231htonl(test) 的情況:     ->其值為: 0x34333231小端機(jī)器:00000010: 31 32 33 34         -> 1234大端機(jī)器:00000010: 34 33 32 31         -> 4321/3. 拿來主義Byte Endian是指字節(jié)在內(nèi)存中的組織,所以也稱它為Byte Ordering,或Byte Orde

5、r。      對(duì)于數(shù)據(jù)中跨越多個(gè)字節(jié)的對(duì)象, 我們必須為它建立這樣的約定:(1) 它的地址是多少?(2) 它的字節(jié)在內(nèi)存中是如何組織的?    針對(duì)第一個(gè)問題,有這樣的解釋:    對(duì)于跨越多個(gè)字節(jié)的對(duì)象,一般它所占的字節(jié)都是連續(xù)的,它的地址等于它所占字節(jié)最低地址。(鏈表可能是個(gè)例外, 但鏈表的地址可看作鏈表頭的地址)。    比如: int x, 它的地址為0x100。 那么它占據(jù)了內(nèi)存中的Ox100, 0x101, 0x102, 0x103這四個(gè)字節(jié)(32位系

6、統(tǒng),所以int占用4個(gè)字節(jié))。    上面只是內(nèi)存字節(jié)組織的一種情況: 多字節(jié)對(duì)象在內(nèi)存中的組織有一般有兩種約定。 考慮一個(gè)W位的整數(shù)。    它的各位表達(dá)如下:Xw-1, Xw-2, . , X1, X0,它的    MSB (Most Significant Byte, 最高有效字節(jié))為 Xw-1, Xw-2, . Xw-8;    LSB (Least Significant Byte, 最低有效字節(jié))為 X7,X6,., X0。    

7、其余的字節(jié)位于MSB, LSB之間。LSB和MSB誰(shuí)位于內(nèi)存的最低地址, 即誰(shuí)代表該對(duì)象的地址? 這就引出了大端(Big Endian)與小端(Little Endian)的問題。如果LSB在MSB前面, 既LSB是低地址, 則該機(jī)器是小端; 反之則是大端。DEC (Digital Equipment Corporation,現(xiàn)在是Compaq公司的一部分)和Intel的機(jī)器(X86平臺(tái))一般采用小端。IBM, Motorola(Power PC), Sun的機(jī)器一般采用大端。當(dāng)然,這不代表所有情況。有的CPU即能工作于小端, 又能工作于大端, 比如ARM, Alpha,摩托羅拉的PowerP

8、C。 具體情形參考處理器手冊(cè)。具體這類CPU是大端還是小端,應(yīng)該和具體設(shè)置有關(guān)。(如,Power PC支持little-endian字節(jié)序,但在默認(rèn)配置時(shí)是big-endian字節(jié)序)一般來說,大部分用戶的操作系統(tǒng)(如windows, FreeBsd,Linux)是Little Endian的。少部分,如MAC OS ,是Big Endian 的。所以說,Little Endian還是Big Endian與操作系統(tǒng)和芯片類型都有關(guān)系。因此在一個(gè)處理器系統(tǒng)中,有可能存在大端和小端模式同時(shí)存在的現(xiàn)象。這一現(xiàn)象為系統(tǒng)的軟硬件設(shè)計(jì)帶來了不小的麻煩,這要求系統(tǒng)設(shè)計(jì)工程師,必須深入理解大端和小端模式的差別

9、。大端與小端模式的差別體現(xiàn)在一個(gè)處理器的寄存器,指令集,系統(tǒng)總線等各個(gè)層次中。Linux系統(tǒng)中,你可以在/usr/include/中(包括子目錄)查找字符串BYTE_ORDER(或_BYTE_ORDER, _BYTE_ORDER),確定其值。BYTE_ORDER中文稱為字節(jié)序。這個(gè)值一般在endian.h或machine/endian.h文件中可以找到,有時(shí)在feature.h中,不同的操作系統(tǒng)可能有所不同?!居煤瘮?shù)判斷系統(tǒng)是Big Endian還是Little Endian】enum FALSE = 0, TRUE = !FALSE;typedef short BOOL;BOOL IsBig

10、_Endian()/如果字節(jié)序?yàn)閎ig-endian,返回true;/反之為   little-endian,返回false    unsigned short test = 0x1122;    if(*( (unsigned char*) &test ) = 0x11)       return TRUE;else    return FALSE;/IsBig_Endian()/可以做個(gè)實(shí)驗(yàn)在windows上下如下

11、程序#include <stdio.h>#include <assert.h>void main( void )        short test;        FILE* fp;                 test = 0x3132; /(31ASIIC碼的1,32ASII

12、C碼的2)        if (fp = fopen ("c:test.txt", "wb") = NULL)              assert(0);        fwrite(&test, sizeof(short), 1, fp);   

13、;     fclose(fp);    然后在C盤下打開test.txt文件,可以看見內(nèi)容是21,而test等于0x3132,可以明顯的看出來x86的字節(jié)順序是低位在前.如果我們把這段同樣的代碼放到(big-endian)的機(jī)器上執(zhí)行,那么打出來的文件就是12.這在本機(jī)中使用是沒有問題的.但當(dāng)你把這個(gè)文件從一個(gè)big- endian機(jī)器復(fù)制到一個(gè)little-endian機(jī)器上時(shí)就出現(xiàn)問題了.    如上述例子,我們?cè)赽ig-endian的機(jī)器上創(chuàng)建了這個(gè)test文件,把其復(fù)制到little-

14、endian的機(jī)器上再用fread讀到一個(gè) short里面,我們得到的就不再是0x3132而是0x3231了,這樣讀到的數(shù)據(jù)就是錯(cuò)誤的,所以在兩個(gè)字節(jié)順序不一樣的機(jī)器上傳輸數(shù)據(jù)時(shí)需要特別小心字節(jié)順序,理解了字節(jié)順序在可以幫助我們寫出移植行更高的代碼.正因?yàn)橛凶止?jié)順序的差別,所以在網(wǎng)絡(luò)傳輸?shù)臅r(shí)候定義了所有字節(jié)順序相關(guān)的數(shù)據(jù)都使用big-endian,BSD的代碼中定義了四個(gè)宏來處理:#define ntohs(n)     /網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序 n代表net, h代表host, s代表short#define htons(n)  

15、;   /主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序 n代表net, h代表host, s代表short#define ntohl(n)      /網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序 n代表net, h代表host, s代表 long#define htonl(n)      /主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序 n代表net, h代表host, s代表 long舉例說明下這其中一個(gè)宏的實(shí)現(xiàn):#define sw16(x)     (short)(   &

16、#160;     (short)(x) & (short)0x00ffU) << 8) |         (short)(x) & (short)0xff00U) >> 8) )這里實(shí)現(xiàn)的是一個(gè)交換兩個(gè)字節(jié)順序.其他幾個(gè)宏類似.我們改寫一下上面的程序#include <stdio.h>#include <assert.h>#define sw16(x)     (short)(  

17、;       (short)(x) & (short)0x00ffU) << 8) |         (short)(x) & (short)0xff00U) >> 8) )#define sw32(x) (long)(    (long)(x) & (long)0x000000ff) << 24) |    (long)(x) & (long)0x000

18、0ff00) << 8) |    (long)(x) & (long)0x00ff0000) >> 8) |    (long)(x) & (long)0xff000000) >> 24) )/ 因?yàn)閤86下面是低位在前,需要交換一下變成網(wǎng)絡(luò)字節(jié)順序#define htons(x) sw16(x)#define htonl(x) sw32(x)void main( void )        short test; 

19、60;      FILE* fp;                 test = htons(0x3132); /(31ASIIC碼的1,32ASIIC碼的2)        if (fp = fopen ("c:test.txt", "wb") = NULL)  &

20、#160;           assert(0);        fwrite(&test, sizeof(short), 1, fp);        fclose(fp);    如果在高字節(jié)在前的機(jī)器上,由于與網(wǎng)絡(luò)字節(jié)順序一致,所以我們什么都不干就可以了,只需要把#define htons(x) sw16(x)宏

21、替換為 #define htons(x) (x).    一開始我在理解這個(gè)問題時(shí),總在想為什么其他數(shù)據(jù)不用交換字節(jié)順序?比如說我們write一塊buffer到文件,最后終于想明白了,因?yàn)槎际莡nsigned char類型一個(gè)字節(jié)一個(gè)字節(jié)的寫進(jìn)去,這個(gè)順序是固定的,不存在字節(jié)順序的問題【大端(Big Endian)與小端(Little Endian)簡(jiǎn)介】Byte Endian是指字節(jié)在內(nèi)存中的組織,所以也稱它為Byte Ordering,或Byte Order。      對(duì)于數(shù)據(jù)中跨越多個(gè)字節(jié)的對(duì)象, 我們必須為它建立這

22、樣的約定:(1) 它的地址是多少?(2) 它的字節(jié)在內(nèi)存中是如何組織的?    針對(duì)第一個(gè)問題,有這樣的解釋:    對(duì)于跨越多個(gè)字節(jié)的對(duì)象,一般它所占的字節(jié)都是連續(xù)的,它的地址等于它所占字節(jié)最低地址。(鏈表可能是個(gè)例外, 但鏈表的地址可看作鏈表頭的地址)。    比如: int x, 它的地址為0x100。 那么它占據(jù)了內(nèi)存中的Ox100, 0x101, 0x102, 0x103這四個(gè)字節(jié)(32位系統(tǒng),所以int占用4個(gè)字節(jié))。    上面只是內(nèi)存字節(jié)組織的一種情況: 多字

23、節(jié)對(duì)象在內(nèi)存中的組織有一般有兩種約定。 考慮一個(gè)W位的整數(shù)。    它的各位表達(dá)如下:Xw-1, Xw-2, . , X1, X0,它的    MSB (Most Significant Byte, 最高有效字節(jié))為 Xw-1, Xw-2, . Xw-8;    LSB (Least Significant Byte, 最低有效字節(jié))為 X7,X6,., X0。     其余的字節(jié)位于MSB, LSB之間。LSB和MSB誰(shuí)位于內(nèi)存的最低地址, 即誰(shuí)代表該對(duì)象的地址? 這就引出

24、了大端(Big Endian)與小端(Little Endian)的問題。如果LSB在MSB前面, 既LSB是低地址, 則該機(jī)器是小端; 反之則是大端。DEC (Digital Equipment Corporation,現(xiàn)在是Compaq公司的一部分)和Intel的機(jī)器(X86平臺(tái))一般采用小端。IBM, Motorola(Power PC), Sun的機(jī)器一般采用大端。當(dāng)然,這不代表所有情況。有的CPU即能工作于小端, 又能工作于大端, 比如ARM, Alpha,摩托羅拉的PowerPC。 具體情形參考處理器手冊(cè)。 具體這類CPU是大端還是小端,應(yīng)該和具體設(shè)置有關(guān)。(如,Power PC支

25、持little-endian字節(jié)序,但在默認(rèn)配置時(shí)是big-endian字節(jié)序)一般來說,大部分用戶的操作系統(tǒng)(如windows, FreeBsd,Linux)是Little Endian的。少部分,如MAC OS ,是Big Endian 的。所以說,Little Endian還是Big Endian與操作系統(tǒng)和芯片類型都有關(guān)系。Linux系統(tǒng)中,你可以在/usr/include/中(包括子目錄)查找字符串BYTE_ORDER(或_BYTE_ORDER, _BYTE_ORDER),確定其值。BYTE_ORDER中文稱為字節(jié)序。這個(gè)值一般在endian.h或machine/endian.h文件

26、中可以找到,有時(shí)在feature.h中,不同的操作系統(tǒng)可能有所不同。          big endian是指低地址存放最高有效字節(jié)(MSB),而little endian則是低地址存放最低有效字節(jié)(LSB)。         用文字說明可能比較抽象,下面用圖像加以說明。比如數(shù)字0x12345678在兩種不同字節(jié)序CPU中的存儲(chǔ)順序如下所示:Big Endian   低地址  

27、0;                                         高地址   ->   +-+-+-+-+-+-+-+-+-+-+-+

28、-+-+-+-+-+-+-+   |     12     |      34    |     56      |     78    |   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Little End

29、ian   低地址                                            高地址   ->&

30、#160;  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   |     78     |      56    |     34      |     12    |   +-+-+-+-+-+-

31、+-+-+-+-+-+-+-+-+-+-+-+-+        從上面兩圖可以看出,采用big endian方式存儲(chǔ)數(shù)據(jù)是符合我們?nèi)祟惖乃季S習(xí)慣的.        為什么要注意字節(jié)序的問題呢?你可能這么問。當(dāng)然,如果你寫的程序只在單機(jī)環(huán)境下面運(yùn)行,并且不和別人的程序打交道,那么你完全可以忽略字節(jié)序的存在。但是,如果你的程序要跟別人的程序產(chǎn)生交互呢?在這里我想說說兩種語(yǔ)言。C/C+語(yǔ)言編寫的程序里數(shù)據(jù)存儲(chǔ)順序是跟編譯平臺(tái)所在的CPU相關(guān)的,而 J*A編寫的

32、程序則唯一采用big endian方式來存儲(chǔ)數(shù)據(jù)。試想,如果你用C/C+語(yǔ)言在x86平臺(tái)下編寫的程序跟別人的J*A程序互通時(shí)會(huì)產(chǎn)生什么結(jié)果?就拿上面的 0x12345678來說,你的程序傳遞給別人的一個(gè)數(shù)據(jù),將指向0x12345678的指針傳給了J*A程序,由于J*A采取big endian方式存儲(chǔ)數(shù)據(jù),很自然的它會(huì)將你的數(shù)據(jù)翻譯為0x78563412。什么?竟然變成另外一個(gè)數(shù)字了?是的,就是這種后果。因此,在你的C程序傳給J*A程序之前有必要進(jìn)行字節(jié)序的轉(zhuǎn)換工作。     無獨(dú)有偶,所有網(wǎng)絡(luò)協(xié)議也都是采用big endian的方式來傳輸數(shù)據(jù)的。所以有時(shí)

33、我們也會(huì)把big endian方式稱之為網(wǎng)絡(luò)字節(jié)序。當(dāng)兩臺(tái)采用不同字節(jié)序的主機(jī)通信時(shí),在發(fā)送數(shù)據(jù)之前都必須經(jīng)過字節(jié)序的轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)序后再進(jìn)行傳輸。ANSI C中提供了下面四個(gè)轉(zhuǎn)換字節(jié)序的宏。·BE和LE一文的補(bǔ)完        我在8月9號(hào)的Big Endian和Little Endian一文中談了字節(jié)序的問題,原文見上面的超級(jí)鏈接??墒怯信笥讶匀粫?huì)問,CPU存儲(chǔ)一個(gè)字節(jié)的數(shù)據(jù)時(shí)其字節(jié)內(nèi)的8個(gè)比特之間的順序是否也有 big endian和little endian之分?或者說是否有比特序的不同?  &

34、#160;   實(shí)際上,這個(gè)比特序是同樣存在的。下面以數(shù)字0xB4(10110100)用圖加以說明。 Big Endian   msb                                   

35、60;                     lsb   ->   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   |   1 |   0 |   1 |   1 |   0 | &

36、#160; 1 |   0 |   0 |   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Little Endian   lsb                             &#

37、160;                           msb   ->   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   |   0 |   0 |   1 |&#

38、160;  0 |   1 |   1 |   0 |   1 |   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+     實(shí)際上,由于CPU存儲(chǔ)數(shù)據(jù)操作的最小單位是一個(gè)字節(jié),其內(nèi)部的比特序是什么樣對(duì)我們的程序來說是一個(gè)黑盒子。也就是說,你給我一個(gè)指向0xB4這個(gè)數(shù)的指針,對(duì)于big endian方式的CPU來說,它是從左往右依次讀取這個(gè)數(shù)的8個(gè)比特;而對(duì)于little endian方式的CPU來說,則正好

39、相反,是從右往左依次讀取這個(gè)數(shù)的8個(gè)比特。而我們的程序通過這個(gè)指針訪問后得到的數(shù)就是0xB4,字節(jié)內(nèi)部的比特序?qū)τ诔绦騺碚f是不可見的,其實(shí)這點(diǎn)對(duì)于單機(jī)上的字節(jié)序來說也是一樣的。     那可能有人又會(huì)問,如果是網(wǎng)絡(luò)傳輸呢?會(huì)不會(huì)出問題?是不是也要通過什么函數(shù)轉(zhuǎn)換一下比特序?嗯,這個(gè)問題提得很好。假設(shè)little endian方式的CPU要傳給big endian方式CPU一個(gè)字節(jié)的話,其本身在傳輸之前會(huì)在本地就讀出這個(gè)8比特的數(shù),然后再按照網(wǎng)絡(luò)字節(jié)序的順序來傳輸這8個(gè)比特,這樣的話到了接收端不會(huì)出現(xiàn)任何問題。而假如要傳輸一個(gè)32比特的數(shù)的話,由于這個(gè)數(shù)在

40、littel endian方存儲(chǔ)時(shí)占了4個(gè)字節(jié),而網(wǎng)絡(luò)傳輸是以字節(jié)為單位進(jìn)行的,little endian方的CPU讀出第一個(gè)字節(jié)后發(fā)送,實(shí)際上這個(gè)字節(jié)是原數(shù)的LSB,到了接收方反倒成了MSB從而發(fā)生混亂?!居煤瘮?shù)判斷系統(tǒng)是Big Endian還是Little Endian】bool IsBig_Endian()/如果字節(jié)序?yàn)閎ig-endian,返回true;/反之為   little-endian,返回false    unsigned short test = 0x1122;    if(*( (unsign

41、ed char*) &test ) = 0x11)       return TRUE;else    return FALSE;/IsBig_Endian()字節(jié)序問題-大端法小端法 收藏 < type="text/java script"> document.body.oncopy = function() if (window.clipboardData) setTimeout(function() var text = clipboardData.getDa

42、ta("text"); if (text && text.length > 300) text = text + "rnn本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:" + location.href; clipboardData.setData("text", text); , 100); 一、字節(jié)序定義字節(jié)序,顧名思義字節(jié)的順序,再多說兩句就是大于一個(gè)字節(jié)類型的數(shù)據(jù)在內(nèi)存中的存放順序(一個(gè)字節(jié)的數(shù)據(jù)當(dāng)然就無需談順序的問題了)。其實(shí)大部分人在實(shí)際的開發(fā)中都很少會(huì)直接和字節(jié)序打交道。唯有在跨平臺(tái)以及網(wǎng)絡(luò)程序中字節(jié)序才是

43、一個(gè)應(yīng)該被考慮的問題。在所有的介紹字節(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é)序:4個(gè)字節(jié)的32 bit值以下面的次序傳輸:首先是07bit,其次815bit,然后1623bit,最后是2431bit。這種傳輸次序稱作大端字節(jié)序。由于 TCP/IP首部中所有的二進(jìn)制整數(shù)在網(wǎng)絡(luò)中傳輸時(shí)都

44、要求以這種次序,因此它又稱作網(wǎng)絡(luò)字節(jié)序。比如,以太網(wǎng)頭部中2字節(jié)的“以太網(wǎng)幀類型”,表示后面數(shù)據(jù)的類型。對(duì)于ARP請(qǐng)求或應(yīng)答的以太網(wǎng)幀類型 來說,在網(wǎng)絡(luò)傳輸時(shí),發(fā)送的順序是0x08,0x06。在內(nèi)存中的映象如下圖所示:棧底 (高地址)-0x06 - 低位 0x08 - 高位-棧頂 (低地址)該字段的值為0x0806。按照大端方式存放在內(nèi)存中。二、高/低地址與高低字節(jié)首先我們要知道我們C程序映像中內(nèi)存的空間布局情況:在C專家編程中或者Unix環(huán)境高級(jí)編程中有關(guān)于內(nèi)存空間布局情況的說明,大致如下圖:- 最高內(nèi)存地址 0xffffffff| 棧底.    &#

45、160;         棧.棧頂-|/NULL (空洞)/|-                堆-未初始化的數(shù)據(jù)-(統(tǒng)稱數(shù)據(jù)段)初始化的數(shù)據(jù)-正文段(代碼段)- 最低內(nèi)存地址 0x00000000以上圖為例如果我們?cè)跅I戏峙湟粋€(gè)unsigned char buf4,那么這個(gè)數(shù)組變量在棧上是如何布局的呢注1?看下圖:棧底 (高地址)-buf3buf2buf1buf0-

46、棧頂 (低地址)現(xiàn)在我們弄清了高低地址,接著來弄清高/低字節(jié),如果我們有一個(gè)32位無符號(hào)整型0x12345678(呵呵,恰好是把上面的那4個(gè)字節(jié)buf看成一個(gè)整型),那么高位是什么,低位又是什么呢?其實(shí)很簡(jiǎn)單。在十進(jìn)制中我們都說靠左邊的是高位,靠右邊的是低位,在其他進(jìn)制也是如此。就拿 0x12345678來說,從高位到低位的字節(jié)依次是0x12、0x34、0x56和0x78。高低地址和高低字節(jié)都弄清了。我們?cè)賮砘仡櫼幌翨ig-Endian和Little-Endian的定義,并用圖示說明兩種字節(jié)序:以u(píng)nsigned int value = char buf4來表示value:Big-Endian

47、: 低地址存放高位,如下圖:棧底 (高地址)-buf3 (0x78) - 低位buf2 (0x56)buf1 (0x34)buf0 (0x12) - 高位-棧頂 (低地址)Little-Endian: 低地址存放低位,如下圖:棧底 (高地址)-buf3 (0x12) - 高位buf2 (0x34)buf1 (0x56)buf0 (0x78) - 低位-棧頂 (低地址)在現(xiàn)有的平臺(tái)上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。三、例子嵌入式系統(tǒng)開發(fā)者應(yīng)該對(duì)Little-endian和Big-endian模式非常了解。采用Little

48、-endian模式的CPU對(duì)操作數(shù)的存放方式是從低字節(jié)到高字節(jié),而Big-endian模式對(duì)操作數(shù)的存放方式是從高字節(jié)到低字節(jié)。例如,16bit寬的數(shù)0x1234在Little-endian模式CPU內(nèi)存中的存放方式(假設(shè)從地址0x4000開始存放)為:內(nèi)存地址 存放內(nèi)容0x4001    0x120x4000    0x34而在Big-endian模式CPU內(nèi)存中的存放方式則為:內(nèi)存地址 存放內(nèi)容0x4001    0x340x4000    0x1232bit寬的數(shù)0x1

49、2345678在Little-endian模式CPU內(nèi)存中的存放方式(假設(shè)從地址0x4000開始存放)為:內(nèi)存地址 存放內(nèi)容0x4003     0x120x4002     0x340x4001     0x560x4000     0x78而在Big-endian模式CPU內(nèi)存中的存放方式則為:內(nèi)存地址 存放內(nèi)容0x4003     0x780x4002   &#

50、160; 0x560x4001     0x340x4000     0x12三、例子 測(cè)試平臺(tái) : Sun SPARC Solaris 9 和 Intel X86 Solaris 9我們的例子是這樣的:在使用不同字節(jié)序的平臺(tái)上使用相同的程序讀取同一個(gè)二進(jìn)制文件的內(nèi)容。 生成二進(jìn)制文件的程序如下 :/* gen_binary.c */int main()         FILE    *fp = NULL;

51、0;       int     value =         int     rv = 0;        fp = fopen("temp.dat", "wb");        if (fp = NUL

52、L)                 printf("fopen errorn");                return -1;             

53、;   rv = fwrite(&value, sizeof(value), 1, fp);        if (rv != 1)                 printf("fwrite errorn");          

54、;      return -1;                fclose(fp);        return 0;讀取二進(jìn)制文件的程序如下: int main()         int      &#

55、160;      value   = 0;        FILE         *fp     = NULL;        int           

56、  rv      = 0;        unsigned        char buf4;        fp = fopen("temp.dat", "rb");        if (fp = NULL) &#

57、160;               printf("fopen errorn");                return -1;                rv = fread(buf, sizeof(unsigned char), 4, fp);        if (rv != 4)                

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論