字節序、字節對齊的理解.docx_第1頁
字節序、字節對齊的理解.docx_第2頁
字節序、字節對齊的理解.docx_第3頁
字節序、字節對齊的理解.docx_第4頁
字節序、字節對齊的理解.docx_第5頁
已閱讀5頁,還剩5頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、 前言作為一名 C/C+ 程序員,字節是我們天天都要與之打交道的一個東西。我們和它熟稔到幾乎已經忘記了它的存在。可是,它自己是不甘寂寞的,或遲或早地,總會在某些時候探出頭 來張望,然后給你一個腿兒絆。其實,只要你真正了解了它的底細,你就會暢行無阻。在本文中,我們將首先簡要了解一下字節的概念,然后著重了解一下字節序問 題和字節對齊問題。2、 什么是字節我們知道,二進制計算機(也就是我們目前接觸到的幾乎所有的計算機)的最小數據單位是位( bit )。一位數據只能夠表示兩種含義(需要說明,盡管我們通常把單個位表示的兩種含義選擇為相互對立的含義,但這并不是必然的,例如你可以認為 1 代表 5 個人, 0 代表 8 個人),對于絕大多數的計算要求,單個位顯然不能滿足。因此,我們通常都會使用一連串的位,我們可以稱之為位串( bit string ,請愛好質疑的的朋友注意,此術語非我杜撰)。由于種種原因,計算機系統都不會讓你使用任意長度的位串,而是使用某個特定長度的位串。一些常見的位串長度 形式具有約定好的名稱,如,半字節( nibble ,貌似用的不多)代表四個位的組合,字節( byte ,主角出場!)代表 8 個位的組合。再多的還有,字( word )、雙字( Double word ,通常簡寫為 Dword )、四字( Quad word ,經常簡寫為 Qword )、十字節( Ten byte ,也簡寫為 Tbyte )。在這些里面,字( word )有時表示不同的含義。在 Intel 體系里, word 表示一個 16 位的數值,它是固定大小的。而在另外一些場合, word 表示了 CPU 一次可處理的數據的位數,表示一個符合 CPU 字長( word-length )的數目的位串。事實上我們接觸較多的 ARM 體系中, word 就有不同的含義,它表示一個 32 位的數據(與機器字長相同),對于 16 位大小的數據, ARM 使用了另外的一個術語,叫作半字( half-word ),請大家在文檔閱讀時加以注意。另外, Qword 也是 Intel 體系中的術語,其他的體系中可能并不使用。在本文中,我們按照 Intel 的慣例來使用字或者 word 這一術語。一個字節中共有 8 個數據位,有時需要用圖表逐位表述各個位。習慣上,我們按照下面的圖來排列各個位的順序,即,按照從右到左的順序,依次為最低位(從第 0 位開始)到最高位(對于字節,則是第 7 位):字節是大多數現代計算機的最小存儲單元,但這并不代表它是計算機可以最高效地處理的數據單位。一般的來說,計算機可以最高效地處理的數據大小,應該 與其字長相同。在目前來講,桌面平臺的處理器字長正處于從 32 位向 64 位過渡的時期,嵌入式設備的基本穩定在 32 位,而在某些專業領域(如高端顯卡),處理器字長早已經達到了 64 位乃至更多的 128 位。3、 字節序問題的由來對于字、雙字這些多于一個字節的數據,如果把它們放置到內存中的某個位置上,可以看出,我們還可以將之看作是字節的序列。一個字是兩個字節,雙字則 是四個字節。假設有以下數據: 0x12345678 、 0x9abcdef0 。在此處,我使用了我們最習慣的十六進制表示法,并給出了兩個雙字的值。按照慣例,我把雙字的左側視為高端,而把右側視為低端。把它們順序放置在起始地址 為 0 的內存中,如下圖所示:由圖示可知, 0x9abcdef 的相應地址為 0x04 。現在,問題來了,如果有一個內存操作,要從地址 0x06 處讀取一個字,得到的結果是多少呢?答案是:不一定。這里的本質問題在于,如何把多字節的對象存儲到內存中去呢?即使使用最正常的思維去考慮這個問題,你也會發現有兩種方法。第一種方法是,把最低端的 字節放到指定的起始位置(即基地址處),然后按照從低到高的字節順序把其余字節依次放入,如下圖 a ;另一種方法非常類似,但是對高端字節和低端字節的處理順序正好相反,如下圖 b (我確信你還可以想出其他的方法,但是除二字節的情況外,必然會打破字節排列順序的一致性,我視之為反常規思維的產物,此處暫不考慮)。圖 a圖 b在很久之前,哪一種存儲方式更為合理曾經有過爭論。到今天,爭論的結果已經無關緊要了,緊要的是以下事實:這兩種存儲方式都被應用到了現實的計算機 系統中。上圖 a 中的排列方式為 Intel 所采用并大行其道,而圖 b 的排列方式則被大多數的其他平臺采用(如最近被蘋果公司徹底拋棄的 PowerPC ),因此上,我們不能稱之為罕見的用法。之所以造成事實上的不經常見到,其原因正如我今天中午所得到的消息: Intel 的 CPU 占整個市場份額的 80% 以上。這兩種排列方式通常用小端( little endian )和大端( big endian )來稱謂。這兩個奇怪的名字據說來源于童話格列佛游記,其中小人國里的公民為了雞蛋到底是應該從小的一頭打開還是大的一頭打開而大起爭執。 Intel 的方式對應于“小端”,順便說一句,大端的方式也有一個大公司的名字作為其代表,即最近開始沒落的 Motorola 。如果有誰了解過 TIFF 圖像文件格式,就會發現其文件頭中用以標識文件數據字節序的標志就是“ II ”和“ MM ”,分別對應于 Intel 和 Motorola 的首字母。值得提醒一下,小端方式的排列與位的排列順序相一致,看上去似乎更協調一些。現在我們可以回答上面的問題了。對于小端字節序,我們取到的字,其值為 0x9abc ,而如果是大端字節序的話,就會取到 0xdef0 。4、 何時會出現字節序問題字節序問題主要出現在數據在不同平臺之間進行交換時,交換的途徑可能是網絡傳輸,也可能是文件復制。例如,如果你設計了一種可能會應用于不同平臺的 文件格式,其中存儲了某些數據結構,則對于大小大于一個字節的數據就要明確地規定其遵循的字節序,以便各平臺上的處理程序可以在使用數據時實現做必要的轉 換。舉一個實際的例子。 Java 是一個跨平臺的編程語言,其可執行文件(擴展名為 .class ,使用的是一種機器無關的字節碼指令集)在理論上可以運行于所有的實現了 Java 運行時的平臺(包含有與特定平臺相關特性的除外)。編譯后的 .class 中一定保存有諸如 Integer 這樣類型的數據,這就涉及到了字節序的確定,否則 .class 必然不能被采用了不同字節序的平臺同時正確加載并運行。事實上, Java 語言采用的為大端字節序,這個一點都不奇怪,因為當初 SUN 公司自己的 SPARC 架構就是采用的大端字節序。同樣的問題和解決問題的方式,也存在于操作系統新貴 android 系統上。網絡傳輸則是另一個典型場景。 TCP/IP 所采用的網絡傳輸字節序標準也是大端字節序,這個也不必奇怪,因為 TCP/IP 是從 UNIX 系統發展起來的,而絕大部分的 UNIX 系統在很長的一段時間內都沒有運行于 Intel 體系架構上的版本。處理字節序問題的手段非常簡單,也就是對數據進行必要的轉換:將十六進制的數字從兩端開始交換,直至移動到數據的中心,交換完成為止。交換的結果就好像物體與鏡面之內的成像互換了位置,因此也被稱為鏡像交換( mirror-image swap )。請參看下圖:5、 如何在程序中判斷字節序在實際的工作中,有時需要對字節序進行判斷,然后予以不同的處理。一般的來說,編譯后的程序通常只能運行在特定的平臺之上,其所采用的字節序方式在 編譯時即可確定,在這種情況下,程序源代碼中通常是把字節序的判別作為條件編譯的判斷語句,而不會判斷代碼放在真正的可執行代碼中。在這里,需要使用我們的老朋友 宏。以下是一個真實的跨平臺工程中代碼,清晰起見,我稍做了修改:#define SGE_LITTLE_ENDIAN 1234#define SGE_BIG_ENDIAN 4321#ifndef SGE_BYTEORDER#if defined(_hppa_) | defined(_m68k_) | defined(mc68000) | defined(_M_M68K) | (defined(_MIPS_) & defined(_MISPEB_) | defined(_ppc_) | defined(_POWERPC_) | defined(_M_PPC) | defined(_sparc_)#define SGE_BYTEORDER SGE_BIG_ENDIAN#else#define SGE_BYTEORDER SGE_LITTLE_ENDIAN#endif#endif以上為根據平臺的預定義宏所作的前期工作,將之存入一個頭文件中,然后包含到源代碼文件中使用。在需要進行判斷的時候,則像以下代碼這樣使用:#if SGE_BYTEORDER = SGE_BIG_ENDIAN #define SwapWordLe(w) SwapWord(w) #else #define SwapWordLe(w) (w) #endif由于這兩個宏實際上被定義成了常量數值,因此也可以被用到可執行代碼中,進行執行期的動態判斷:if(SGE_BYTEORDER = SGE_BIG_ENDIAN) return r 16 | g 8 | b; else return r | g 8 | b y; / 執行一個非對齊的讀取操作typedef struct short x; char y; _pac

溫馨提示

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

評論

0/150

提交評論