关于endian
關(guān)于endian這個詞Pconline上的解釋如下:
“endian”這個詞出自《格列佛游記》。小人國的內(nèi)戰(zhàn)就源于吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開,由此曾發(fā)生過六次叛亂,其中一個皇帝送了命,另一個丟了王位。
我們一般將endian翻譯成“字節(jié)序”,將big endian和little endian稱作“大尾”和“小尾”。還挺有趣的,不是嗎?這些黑客們又同時是奇客(geek),總喜歡在學(xué)問中搞出些小小的“玩笑”來調(diào)劑自己的生活,并樂在其中,它和做學(xué)問的時侯的嚴(yán)謹(jǐn)完美的結(jié)合在黑客身上,還顯得如此的協(xié)調(diào)!
初次遇到關(guān)于endian的問題是在學(xué)習(xí)網(wǎng)絡(luò)編程的時侯,因?yàn)槎丝谔栆M(jìn)行字節(jié)序列的轉(zhuǎn)換,所以那本書簡單地解釋了endian,并對big endian和little endian做如下解釋:
- Big endian: 當(dāng)存儲一個超過一個字節(jié)的數(shù)據(jù)類型時,將其中的高位放在低地址的地方,低位放在高地址的地方。
- Little endian: 于Big endian恰恰相反。
不久前在Linux的內(nèi)核里面再次遇到關(guān)于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 }; |
Google到了一些資料,看了之后只發(fā)覺自己更加的模糊,似乎有些文章的作者自己也不是很明白,看來這個工作之能靠自己測試了。經(jīng)過幾個程序的簡單測試之后,終于找到了一個簡單的endian分析方法,先描述如下(希望我的晦澀的言語您能讀懂):
當(dāng)需要用多個字節(jié)來描述一個數(shù)據(jù)類型,或者是一個數(shù)據(jù)結(jié)構(gòu)中包含多個字段時,各個字段和存儲區(qū)塊中的地址的映射關(guān)系如下:
- big endian: 存儲的區(qū)塊按照地址從低到高的順序以字節(jié)為單位從左到右排列,劃分字段的時侯,從左到右依次劃分。
- little endian: 存儲的區(qū)塊按照地址從高到低的順序以字節(jié)為單位從左到右排列,劃分的時侯,從右到左依次劃分。
| u_int16_t x = 0x1; u_int8_t xx[2]; memcpy(xx, x); |
答案是不固定的,如果是在big endian的計算機(jī)上:
應(yīng)用第一條規(guī)則,從xx中從取出兩個字節(jié)x[0], x[1]。我們知道x[1]的地址肯定比x[0]高,所以排列如下:
| x[0] x[1] --------- 15 ...? 0 --------- 00??? 01 |
如果是little endian的計算機(jī):
應(yīng)用第二條規(guī)則:
| x[1] x[0] --------- 15 ...? 0 --------- ?00?? 01 |
仔細(xì)看看結(jié)論是不是和在文章開始的判別方法給出的結(jié)論是相同的?所以在一定程度上,我們可以認(rèn)為前一個結(jié)論是后一個結(jié)論的推論。
讓我們看個更加復(fù)雜一點(diǎn)的例子:
| 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 = ? |
當(dāng)然又是和endian有關(guān)的問題,分類分析了:
big endian:
| --------------------- | 7-4|3-0 | 7-4|3-0 | --------------------- |? a[0]?? |?? a[1]? | --------------------- | a4 |??? b8?? | c4 | --------------------- | 01 | 02 | 03 | 04 | --------------------- |???? 0x01020304??? | --------------------- |
little endian:
| --------------------- | 7-4|3-0 | 7-4|3-0 | --------------------- |? a[1]?? |?? a[0]? | --------------------- | c4 |??? b8?? | a4 | --------------------- | 04 | 02 | 03 | 01 | --------------------- |???? 0x04020301 ?? | --------------------- |
就是這么簡單,如果你真的懂了的話!
iphdr的那個結(jié)構(gòu)就不用我來分析了吧?
轉(zhuǎn)載于:https://www.cnblogs.com/omygod/archive/2006/11/26/573048.html
總結(jié)
- 上一篇: 如意云使用经验
- 下一篇: 如何有效分配自己的精力