大端(Big Endian)/小端(Little Endian)字節序
參考文章:
- 阮一峯的網絡日誌:理解字節序(圖片取自這裏)
- Wikipedia:Endianness
- How to teach endian
大端字節序 與 小端字節序
在計算機中存在這樣一個問題:如何表示各種各樣的數據?
對於圖片等文件來說,有固定的格式文檔參考。
而對於整數來說,計算機應該如何表示?
它的定義一定包括整數的大小、是否帶符號以及符號是什麼、使用什麼編碼格式表示(一般都是二進制補碼),還有很重要的一點:字節順序。
字節應該從右向左讀還是從左向右讀呢?
這種讀取的順序就稱爲:字節序(Byte-order / Endianness)
字節序分爲兩種:大端字節序(Big Endian,從左向右)和小端字節序(Big Endian,從右向左)
換句話說
大端字節序高位字節在前,低位字節在後
小端字節序低位字節在前,高位字節在後
從一個十六進制數字0x1234
開始:
大端字節序
大端字節序是人類處理自然語言的做法,符合人類從左向右讀的閱讀習慣。
在這種規範下,十六進制數會先存儲0x12作爲高字節,接下來存儲0x34。
小端字節序
低位字節在前,高位字節在後,也就是會以0x3412的形式存儲。
注意!
字節序是以字節爲單位定義的,在一個字節中,兩個半字節仍然是以大端的形式存在。
疑問?
爲什麼要區分字節序?這樣複雜的意義是什麼?
小端字節序的意義
小端字節序對於邏輯電路更有效率。邏輯電路先處理低位字節更有效率,因爲計算都是從低位開始的,計算機中的內部處理邏輯都是使用小端字節序。
但是,大多數的網絡協議和文件格式都是大端字節序,這樣對用戶更加友好。
既然有區分,在使用時肯定要使用一定的解析規則,下面進行簡要介紹。
字節序的處理
對於大端字節序,計算機先讀到的是高位字節,後讀到的是低位字節。而小端字節序恰好相反。
字節序的處理:只有在讀取的時候才需要區分字節序,其他情況都不需要處理。
處理器讀取外部數據時,必須知道數據的字節序纔可以將其轉化成正確的值。接下來就可以正常使用這個值,不需要再考慮字節序。而向外部設備寫數據的時候,也不需要考慮字節序,正常寫入一個值即可,外部設備會自己處理字節序的問題。
例如,處理器讀入一個16位整數
大端字節序會按照如下方法轉值:
x = buf[offset] * 256 + buf[offset+1];
其中buf
是整個數據塊在內存中的起始地址,offset
表示偏移量,也就是正在讀取的位置。第一個字節乘以256,再加上第二個字節,就是大端字節序的值,這個式子可以用邏輯運算符改寫。即:
x = buf[offset]<<8 | buf[offset+1];
編譯器總是將乘2的冪轉換成移位指令,這樣更加方便!左移八位,即在後面添加8個0。
小端字節序會按照如下方法轉值:
x = buf[offset+1] * 256 + buf[offset];
32位整數的求值公式也是一樣的
/* 大端字節序 */
i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24);
/* 小端字節序 */
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);