更新時(shí)間:2018-01-24 來(lái)源:黑馬程序員 瀏覽量:
學(xué)習(xí)底層編程或逆向的童鞋,肯定對(duì)這兩個(gè)名詞并不陌生吧?!今天就給大家介紹一下這兩個(gè)概念.
科普:
大端和小端,老外叫 Big-Endian 和 Little-Endian,其實(shí)指的都是同一個(gè)東東在計(jì)算機(jī)界,表示數(shù)據(jù)在存儲(chǔ)器中的存放順序。不同的 CPU、操作系統(tǒng)對(duì)待數(shù)據(jù)的存儲(chǔ)方式各有不同,但一般常見(jiàn)的操作系統(tǒng)都是小端,而通訊協(xié)議則是大端。
但并不是說(shuō)系統(tǒng)是小端形式存儲(chǔ),文件就一定要采用小端的形式,不同的應(yīng)用程序?qū)τ谧陨頂?shù)據(jù)的存儲(chǔ)方式也各有千秋(自家數(shù)據(jù)愛(ài)咋放咋放,有些還打亂了加密呢),比如:
* Adobe PS -- 大端
* BMP -- 小端
* GIF -- 小端
* JPEG -- 大端
* MacPaint -- 大端
* RTF -- 小端
那么小端和大端有什么區(qū)別呢?舉個(gè)栗子大家就明了了:
比如 0x12345678 這個(gè)數(shù):
* 大端法在內(nèi)存中按字節(jié)依次存放為:12 34 56 78
* 小端法在內(nèi)存中按字節(jié)依次存放為:78 56 34 12
解釋?zhuān)?/p>
大端:較高的有效字節(jié)存放在較低的存儲(chǔ)器地址,較低的有效字節(jié)存放在較高的存儲(chǔ)器地址。
比如整型變量 0x12345678 占 4 個(gè)字節(jié),那么根據(jù)內(nèi)存地址從小到大它們的存放方式如下:
小端:較高的有效字節(jié)存放在較高的的存儲(chǔ)器地址,較低的有效字節(jié)存放在較低的存儲(chǔ)器地址。所以整型變量 0x12345678 根據(jù)內(nèi)存地址從小到大它們的存放方式如下:
轉(zhuǎn)換:
我們發(fā)現(xiàn)一個(gè)字節(jié)是可以存放兩個(gè)十六進(jìn)制的數(shù)字的(一個(gè)字節(jié)最大可以存放的數(shù)是 0xFF),那如果給你一個(gè)十進(jìn)制數(shù)(比如 112233),如何快速地知道它在內(nèi)存中是如何存放的呢?
l 大端法很容易,直接將它轉(zhuǎn)換成十六進(jìn)制,然后依次存放即可:0x0001B669
l 小端法則比較麻煩,步驟依次如下:
* 轉(zhuǎn)換成十六進(jìn)制數(shù)(0x0001B669)
* 將八位數(shù)字的低四位和高四位互換(0xB6690001)
* 在低四位和高四位中,分別進(jìn)行兩兩互換(0x69B60100)
如何檢測(cè)你的機(jī)器是大端還是小端?
前邊已經(jīng)說(shuō)過(guò),常見(jiàn)的個(gè)人電腦大多數(shù)都是使用小端,但是我們都是我改變世界的程序猿,不妨考慮小如何使用代碼來(lái)分辨?
其實(shí)不難,通過(guò)將int強(qiáng)轉(zhuǎn)為插入單字節(jié),判斷其實(shí)儲(chǔ)存位置:
#include
int main()
{
int a = 0x2233;
char *b = (char *)&a;
if (*b == 0x22)
{
printf("大端!\n");
}
else
{
printf("小端!\n");
}
return 0;
}
彩蛋
大端和小端,事實(shí)上是來(lái)源于 Jonathan Swift 的《格列佛游記》一書(shū)。
以下是 Jonathan Swift 在 1726 年關(guān)于大小端之爭(zhēng)歷史的描述:
……我下面要告訴你的是,Lilliput 和 Blefuscu 這兩大強(qiáng)國(guó)在過(guò)去 36 個(gè)月里一直在苦戰(zhàn)。戰(zhàn)爭(zhēng)開(kāi)始是由于以下的原因:我們大家都認(rèn)為,吃雞蛋前,原始的方法是打破雞蛋較大的一端,可是當(dāng)今皇帝的祖父小時(shí)候吃雞蛋,一次按古法打雞蛋時(shí)碰巧將一個(gè)手指弄破了,因此他的父親,當(dāng)時(shí)的皇帝,就下了一道敕令,命令全體臣民吃雞蛋時(shí)打破雞蛋較小的一端,違令者重罰。老百姓們對(duì)這項(xiàng)命令極為反感。歷史告訴我們,由此曾發(fā)生過(guò) 6 次叛亂,其中一個(gè)皇帝送了命,另一個(gè)丟了王位。這些叛亂大多都是由 Blefuscu 的國(guó)王大臣們煽動(dòng)起來(lái)的。叛亂平息后,流亡的人總是逃到那個(gè)帝國(guó)去尋救避難。據(jù)估計(jì),先后幾次有 11000 人情愿受死也不肯去打破雞蛋較小的一端。關(guān)于這一爭(zhēng)端,曾出版過(guò)幾百本大部著作,不過(guò)大端派的書(shū)一直是受禁的,法律也規(guī)定該派的任何人不得做官……
在他那個(gè)時(shí)代,Swift 是在諷刺英國(guó)(Lilliput)和法國(guó)(Blefuscu)之間持續(xù)的沖突。Danny Cohen,一位網(wǎng)絡(luò)協(xié)議的早期開(kāi)創(chuàng)者,第一次使用這兩個(gè)術(shù)語(yǔ)來(lái)指代字節(jié)順序,后來(lái)這個(gè)術(shù)語(yǔ)就被廣泛地接納了。
好, 今天的知識(shí)點(diǎn)講解就到這里, 希望大家學(xué)習(xí)愉快!
本文版權(quán)歸黑馬程序員C/C++學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:黑馬程序員C/C++培訓(xùn)學(xué)院
首發(fā):http://c.itheima.com/