字节序——Big Endian和Little Endian
Big Endian和Little Endian
- 一、Endian 的起源
- 二、字節(jié)序之 Little-Endian&Big-Endian
- 三、為什么要注意字節(jié)序
- 四、網(wǎng)絡(luò)序和主機序
- 五、Go 中的字節(jié)序
一、Endian 的起源
在各種計算機體系結(jié)構(gòu)中,對于字節(jié)、字等的存儲機制有所不同,因而引發(fā)了計算機通信領(lǐng)域中一個很重要的問題,即通信雙方交流的信息單元(比特、字節(jié)、字、雙字等等)應(yīng)該以什么樣的順序進行傳送。如果不達(dá)成一致的規(guī)則,通信雙方將無法進行正確的編/譯碼從而導(dǎo)致通信失敗。
1980 年,Danny Cohen 在其著名的論文”O(jiān)n Holy Wars and a Plea for Peace”中為了平息一場關(guān)于在消息中字節(jié)該以什么樣的順序進行傳送的爭論而引用了該詞。該文中,Cohen 非常形象貼切地把支持從一個消息序列的最高位開始傳送的那伙人叫做 Big-Endians,支持從最低位開始傳送的相對應(yīng)地叫做 Little-Endians。此后 Endian 這個詞便隨著這篇論文而被廣為采用。
二、字節(jié)序之 Little-Endian&Big-Endian
首先,明確一點,咱們接觸到的物理單元最小都是字節(jié);因此,無論是 big endian,還是 little endian,都是針對多個字節(jié)的序列而言的;當(dāng)然,在通信領(lǐng)域中,這里往往是 bit,不過原理也是類似的
對于字節(jié)序列的存儲格式,目前有兩大陣營,那就是 Motorola 的 PowerPC 系列 CPU 和 Intel 的 x86 系列 CPU。PowerPC 系列采用 big endian 方式存儲數(shù)據(jù),而 x86 系列則采用 little endian 方式存儲數(shù)據(jù)。那么究竟什么是 big endian,什么又是 little endian 呢?
-
Little-endian:將低序字節(jié)存儲在起始地址(低位編址)
-
Big-endian:將高序字節(jié)存儲在起始地址(高位編址)
案例:
注:每個地址存 1 個字節(jié),2 位 16 進制數(shù)是 1 個字節(jié)(0xFF=11111111)
上面的圖已經(jīng)夠直觀了。也就是說:
- Big Endian 是指低地址端 存放 高位字節(jié)。
- Little Endian 是指低地址端 存放 低位字節(jié)。
各自的優(yōu)勢:
- Big Endian:符號位的判定固定為第一個字節(jié),容易判斷正負(fù)。
- Little Endian:長度為 1,2,4 字節(jié)的數(shù),排列方式都是一樣的,數(shù)據(jù)類型轉(zhuǎn)換非常方便。
三、為什么要注意字節(jié)序
如果你寫的程序只在單機環(huán)境下面運行,并且不和別人的程序打交道,那么你完全可以忽略字節(jié)序的存在。
但是,如果你的程序要跟別人的程序產(chǎn)生交互呢? 比如,當(dāng)一個 C/C++ 的程序要與一個 Java 程序交互時:
-
C/C++語言編寫的程序里數(shù)據(jù)存儲順序是跟編譯平臺所在的 CPU 相關(guān)的,而現(xiàn)在比較普遍的 x86 處理器是 Little Endian
-
JAVA 編寫的程序則唯一采用 Big Endian 方式來存儲數(shù)據(jù)
-
Go 編寫的程序可自主選擇使用哪個字節(jié)序,有開發(fā)者來約定
試想,如果你的 C/C++程序?qū)⒆兞?a = 0x12345678 的首地址傳遞給了 Java 程序,由于 Java 采取 Big Endian 方式存儲數(shù)據(jù),很自然的它會將你的數(shù)據(jù)翻譯為 0x78563412。顯然,問題就出現(xiàn)了!!!
另外,網(wǎng)絡(luò)傳輸一般采用 Big Endian,也被稱之為網(wǎng)絡(luò)字節(jié)序,或網(wǎng)絡(luò)序。當(dāng)兩臺采用不同字節(jié)序的主機通信時,在發(fā)送數(shù)據(jù)之前都必須經(jīng)過字節(jié)序的轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)序后再進行傳輸。
四、網(wǎng)絡(luò)序和主機序
網(wǎng)絡(luò)字節(jié)序: TCP/IP 各層協(xié)議將字節(jié)序定義為 Big Endian,因此 TCP/IP 協(xié)議中使用的字節(jié)序是大端序。
主機字節(jié)序: 整數(shù)在內(nèi)存中存儲的順序,現(xiàn)在 Little Endian 比較普遍。(不同的 CPU 有不同的字節(jié)序)
在進行網(wǎng)絡(luò)通信時 通常需要調(diào)用相應(yīng)的函數(shù)進行主機序和網(wǎng)絡(luò)序的轉(zhuǎn)換。
五、Go 中的字節(jié)序
Go 中處理大小端序的代碼位于 encoding/binary包,其中全局變量 BigEndian 用于操作大端序數(shù)據(jù),LittleEndian 用于操作小端序數(shù)據(jù),這兩個變量所對應(yīng)的數(shù)據(jù)類型都實行了 ByteOrder 接口:
type ByteOrder interface {Uint16([]byte) uint16Uint32([]byte) uint32Uint64([]byte) uint64PutUint16([]byte, uint16)PutUint32([]byte, uint32)PutUint64([]byte, uint64)String() string}其中,前三個方法用于讀取數(shù)據(jù),后三個方法用于寫入數(shù)據(jù)。
大家可能會注意到,上面的方法操作的都是無符號整型,如果我們要操作有符號整型的時候怎么辦呢?很簡單,強制轉(zhuǎn)換就可以了,比如這樣:
func PutInt32(b []byte, v int32) {binary.BigEndian.PutUint32(b, uint32(v)) }為了程序的兼容,我們在開發(fā)跨服務(wù)器的 TCP 服務(wù)時,每次發(fā)送和接受數(shù)據(jù)都要進行轉(zhuǎn)換,這樣做的目的是保證代碼在任何計算機上執(zhí)行時都能達(dá)到預(yù)期的效果。
參考:
go 語言的字節(jié)序
Big Endian 和 Little Endian 詳解
字節(jié)序:Big Endian 和 Little Endian
總結(jié)
以上是生活随笔為你收集整理的字节序——Big Endian和Little Endian的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 可以不用在应用中实现苹果登录了
- 下一篇: 认知天性读书笔记