About Endian
我們一般將endian翻譯成“字節序”,將big endian和little endian稱作“大尾”和“小尾”。
在網絡編程的時侯,因為端口號要進行字節序列的轉換,涉及endian:
Big endian: 當存儲一個超過一個字節的數據類型時,將其中的高位放在低地址的地方,低位放在高地址的地方。
Little endian: 于Big endian恰恰相反。
File: include/linux/ip.h
| 82 struct iphdr { 83 #if defined(__LITTLE_ENDIAN_BITFIELD) 84 __u8 ihl:4, 85 version:4; 86 #elif defined (__BIG_ENDIAN_BITFIELD) 87 __u8 version:4, 88 ihl:4; 89 #else 90 #error "Please fix <asm/byteorder.h>" 91 #endif 92 __u8 tos; 93 __be16 tot_len; 94 __be16 id; 95 __be16 frag_off; 96 __u8 ttl; 97 __u8 protocol; 98 __u16 check; 99 __be32 saddr; 100 __be32 daddr; 101 /*The options start here. */ 102 }; |
當看到83-91行的代碼的時侯,難道在小于自己單位的bit之中也存在endian的問題?
當需要用多個字節來描述一個數據類型,或者是一個數據結構中包含多個字段時,各個字段和存儲區塊中的地址的映射關系如下:
?
- big endian: 存儲的區塊按照地址從低到高的順序以字節為單位從左到右排列,劃分字段的時侯,從左到右依次劃分。
- little endian: 存儲的區塊按照地址從高到低的順序以字節為單位從左到右排列,劃分的時侯,從右到左依次劃分。
現在簡單的給大家舉幾個簡單的例子:
| u_int16_t x = 0x1; u_int8_t xx[2]; memcpy(xx, x); |
在上面的代碼中,最終xx[0]和xx[1]都是什么呢?
答案是不固定的,如果是在big endian的計算機上:
應用第一條規則,從xx中從取出兩個字節x[0], x[1]。我們知道x[1]的地址肯定比x[0]高,所以排列如下:
| x[0] x[1] --------- 15 ... 0 --------- 00 01 |
很明顯x[0] == 0, x[1] == 1.
如果是little endian的計算機:
應用第二條規則:
| x[1] x[0] --------- 15 ... 0 --------- 00 01 |
結果為x[0] == 1, x[1] == 0.
仔細看看結論是不是和在文章開始的判別方法給出的結論是相同的?所以在一定程度上,我們可以認為前一個結論是后一個結論的推論。
讓我們看個更加復雜一點的例子:
| union { u_int16_t num; struct { u_int8_t a4 : 4; u_int8_t b8; u_int8_t c4 : 4; } b; } a; a.b.a4 = 0x01; a.b.b8 = 0x0203; a.b.c4 = 0x04; a.num = ? |
| ? |
這個是不是復雜了很多,不要說實際中這樣的應用不多,看看Linux內核中數據結構你就會明白,類似結構還是蠻多的。
當然又是和endian有關的問題,分類分析了:
big endian:
| --------------------- | 7-4|3-0 | 7-4|3-0 | --------------------- | a[0] | a[1] | --------------------- | a4 | b8 | c4 | --------------------- | 01 | 02 | 03 | 04 | --------------------- | 0x01020304 | --------------------- |
所以,a.num = 0x01020304
little endian:
| --------------------- | 7-4|3-0 | 7-4|3-0 | --------------------- | a[1] | a[0] | --------------------- | c4 | b8 | a4 | --------------------- | 04 | 02 | 03 | 01 | --------------------- | 0x04020301 | --------------------- |
所以,a.num = 0x04020301
總結
以上是生活随笔為你收集整理的About Endian的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 环路补偿之“反向零点”分析 ---- 以
- 下一篇: Android TextView设置.9