最全大端小端詳解(含代碼詳細(xì)注釋)

之前文章《淺談ARM ABI沐绒,Android ABI》中有提到計劃專門一篇文章講下大小端任内,今天兌現(xiàn)一下。

1>"大端" "小端"的來源

關(guān)于大端小端名詞的由來,網(wǎng)傳有一個有趣的故事捏悬,可以追溯到1726年的Jonathan Swift的《格列佛游記》悼瓮,其中一篇講到有兩個國家因?yàn)槌噪u蛋究竟是先打破較大的一端還是先打破較小的一端而爭執(zhí)不休,甚至爆發(fā)了戰(zhàn)爭仍律。

《格利佛游記》:“Lilliput和Blefuscu這兩個強(qiáng)國在過去的36個月中一直在苦戰(zhàn)。戰(zhàn)爭的原因是:我們都知道实柠,吃雞蛋的時候水泉,原始的方法是打破雞蛋較大的一端,可是那時的皇帝的祖父由于小時侯吃雞蛋窒盐,按這種方法把手指弄破了草则,因此他的父親,就下令蟹漓,命令所有的子民吃雞蛋的時候炕横,必須先打破雞蛋較小的一端,違令者重罰葡粒。然后老百姓對此法令極為反感份殿,由此發(fā)生了多次叛亂,產(chǎn)生叛亂的原因就是另一個國家Blefuscu的國王大臣煽動起來的嗽交。叛亂平息后卿嘲,流亡的人就逃到這個帝國避難。據(jù)估計夫壁,先后幾次有11000余人情愿si也不肯去打破雞蛋較小的端吃雞蛋拾枣。”

Swift的《格列佛游記》其實(shí)是在諷刺當(dāng)時英國(Lilliput)和法國(Blefuscu)之間持續(xù)的沖突盒让。

現(xiàn)在以大端梅肤、小端的命名Big-Endian、Little-Endian看邑茄,確實(shí)也符合雞蛋的特征姨蝴,一切源于生活。

2> 計算機(jī)中“大端”“小端”是指什么

大端小端真正引入計算機(jī)領(lǐng)域肺缕,是來自于一位網(wǎng)絡(luò)協(xié)議的早期開創(chuàng)者Danny Cohen左医,他第一次使用這兩個術(shù)語指代字節(jié)順序,后來慢慢被大家廣泛接受搓谆。

字節(jié)順序說的到底是什么炒辉,先復(fù)習(xí)一個基礎(chǔ)知識:

位(bit):計算機(jī)中的最小數(shù)據(jù)單位,計算機(jī)存儲的都是二進(jìn)制0和1這兩個鬼泉手。

字節(jié)(Byte):字節(jié)是存儲空間的基本計量單位黔寇,也是內(nèi)存的基本單位,也是編址單位斩萌。例如缝裤,一個計算機(jī)的內(nèi)存是4GB屏轰,就是該計算機(jī)的內(nèi)存中共有4×1024×1024×1024個字節(jié),意味著它有4G的內(nèi)存尋址空間憋飞。

換算關(guān)系:

1 GB = 1024 MB

1 MB = 1024 KB

1 KB = 1024 Bytes

1 Byte = 8 bits

【Q】:思考一個問題霎苗,通常描述32位二進(jìn)制數(shù)據(jù),為什么是用8個十六進(jìn)制數(shù)呢榛做?如0x1A2B3C4D

【A】:十六進(jìn)制(hex)是一種逢16進(jìn)1的進(jìn)位制唁盏。十六進(jìn)制的數(shù)碼有1,2检眯,3厘擂,4,5锰瘸,6刽严,7,8避凝,9舞萄,A(10),B(11),C(12),D(13),E(14),F(15)。

第一種理解:

4個二進(jìn)制bit 表示的數(shù)值范圍是從00001111管削,即015, 剛好等同于 一位 16進(jìn)制數(shù)的數(shù)值范圍0~F(15)倒脓。

所以可以類推得出:

1Byte = 8bit;即1個字節(jié)包含8個二進(jìn)制bit佩谣,8個二進(jìn)制bit對應(yīng)需要2位十六進(jìn)制數(shù)來表示(最大值為 0xFF)把还;

4Byte = 32bit; 即4個字節(jié)包含32個二進(jìn)制bit实蓬,32個二進(jìn)制bit對應(yīng)需要8位十六進(jìn)制數(shù)來表示茸俭;(最大值為 0xFFFFFFFF);

第二種理解:

因?yàn)?6=2^4(2的4次方)安皱,所以1位十六進(jìn)制數(shù)可以轉(zhuǎn)化為4位二進(jìn)制數(shù)调鬓,即十六進(jìn)制的每個字符需要用4位二進(jìn)制位來表示,如0x0為0000酌伊,0xF為1111腾窝,即1個16進(jìn)制數(shù)為4位二進(jìn)制bit。

所以反推32位二進(jìn)制數(shù)換算為十六進(jìn)制數(shù)后的位數(shù)就變?yōu)?2÷4=8位居砖,即32位二進(jìn)制地址信息需要8位十六進(jìn)制數(shù)表示虹脯。

總結(jié)如下:

4個二進(jìn)制位(bit)(不夠表示一個字節(jié)) = 1個十六進(jìn)制(hex)。

8個二進(jìn)制位(bit) = 一個字節(jié)(Byte) = 2個十六進(jìn)制(hex)奏候。

32個二進(jìn)制位(bit) = 四個字節(jié)(Byte) = 8個十六進(jìn)制(hex)循集。

所以針對一個32位的數(shù)值,如0x1A2B3C4D蔗草,總共四個字節(jié)咒彤,兩個十六進(jìn)制數(shù)表示一個字節(jié)疆柔,高位字節(jié)為0x1A,低位字節(jié)為0x4D镶柱;中間兩個字節(jié)分別為0x2B0x3C旷档;

數(shù)值0x1A2B3C4D想要在計算機(jī)中正確使用,就必須要考慮在內(nèi)存中將其對應(yīng)的四個字節(jié)合理存儲歇拆。假設(shè)內(nèi)存的地址都是從低到高分配的鞋屈,那么對于一個數(shù)值多個字節(jié)順序存儲就有兩種存儲方式:

方式一、數(shù)值的高位字節(jié)存放在內(nèi)存的低地址端故觅,低位字節(jié)存放在內(nèi)存的高地址端:

內(nèi)存低地址 --------------------> 內(nèi)存高地址

0x1A | 0x2B | 0x3C | 0x4D

高位字節(jié) <-------------------- 低位字節(jié)

方式二谐区、數(shù)值的低位字節(jié)存放在內(nèi)存的低地址端,高位字節(jié)存放在內(nèi)存的高地址端:

內(nèi)存低地址 --------------------> 內(nèi)存高地址

0x4D | 0x3C | 0x2B | 0x1A

低位字節(jié) --------------------> 高位字節(jié)

方式一 逻卖,我們就稱之為 大端模式宋列;即高位字節(jié)放在內(nèi)存的低地址端,低位字節(jié)放在內(nèi)存的高地址端评也。

方式二 炼杖,我們就稱之為 小端模式;即低位字節(jié)放在內(nèi)存的低地址端盗迟,高位字節(jié)放在內(nèi)存的高地址端坤邪。

畫圖更直觀理解一下:

image
image

總結(jié)一下:

大端小端是不同的字節(jié)順序存儲方式,統(tǒng)稱為字節(jié)序罚缕;

大端模式艇纺,是指數(shù)據(jù)的高字節(jié)位 保存在 內(nèi)存的低地址中,而數(shù)據(jù)的低字節(jié)位 保存在 內(nèi)存的高地址中邮弹。這樣的存儲模式有點(diǎn)兒類似于把數(shù)據(jù)當(dāng)作字符串順序處理:地址由小向大增加黔衡,而數(shù)據(jù)從高位往低位放。和我們”從左到右“閱讀習(xí)慣一致腌乡。

小端模式盟劫,是指數(shù)據(jù)的高字節(jié)位 保存在 內(nèi)存的高地址中,而數(shù)據(jù)的低字節(jié)位 保存在 內(nèi)存的低地址中与纽。這種存儲模式將地址的高低和數(shù)據(jù)位權(quán)有效地結(jié)合起來侣签,高地址部分權(quán)值高,低地址部分權(quán)值低急迂,和我們的邏輯方法一致影所。

分享一個私人口語化記憶小技巧:

大端模式:“【低位】字節(jié)卻硬要存在【高位】地址中“。---“低對高(或高對低)僚碎,門不當(dāng)戶不對猴娩,真令人頭大”,記作大端模式。

小端模式:“【低位】字節(jié)正好存在【低位】地址中”胀溺。--- “低對低裂七,門當(dāng)戶對,你儂我儂”仓坞,記作小端模式背零。

3> 為什么要學(xué)習(xí)理解“大端”“小端”

大端模式:

基于其存儲特點(diǎn),符號位在所表示的數(shù)據(jù)的內(nèi)存的第一個字節(jié)中无埃,便于快速判斷數(shù)據(jù)的正負(fù)和大嗅闫俊(CPU做數(shù)值運(yùn)算時從內(nèi)存中依順序依次從低位地址到高位地址取數(shù)據(jù)進(jìn)行運(yùn)算,大端就會最先拿到數(shù)據(jù)的(高字節(jié)的)符號位)嫉称。

小端模式:

基于其存儲特點(diǎn)侦镇,內(nèi)存的低地址處存放低字節(jié),所以在強(qiáng)制轉(zhuǎn)換數(shù)據(jù)時不需要調(diào)整字節(jié)的內(nèi)容(比如织阅,把int---4字節(jié)強(qiáng)制轉(zhuǎn)換成short---2字節(jié)壳繁,就可以直接把int數(shù)據(jù)存儲的前兩個字節(jié)給short就行,因?yàn)槠淝皟蓚€字節(jié)剛好就是最低的兩個字節(jié)荔棉,符合轉(zhuǎn)換邏輯闹炉;另外CPU做數(shù)值運(yùn)算時從內(nèi)存中依順序依次從低位地址到高位地址取數(shù)據(jù)進(jìn)行運(yùn)算,開始只管取值润樱,最后刷新最高位地址的符號位就行渣触,這樣的運(yùn)算方式會更高效一些)。

因?yàn)閮煞N模式各有優(yōu)點(diǎn)壹若,存在“你有我無嗅钻,你無我有”的特點(diǎn),所以造就了不同的硬件廠商基于不同的效率(角度)考慮店展,有了不同的硬件設(shè)計支持养篓,最終形成了計算機(jī)各個相關(guān)領(lǐng)域目前并沒有采用統(tǒng)一的字節(jié)序,沒有統(tǒng)一標(biāo)準(zhǔn)的現(xiàn)狀壁查。

其實(shí)也不難理解觉至,就好比文章開頭描述的“吃雞蛋方式之爭一樣” 天下之大又有誰能站出來限定或證明,吃雞蛋必須從“小端”開始睡腿,就一定比從“大端”開始 好?或者 吃雞蛋必須從“大端”開始峻贮,就一定比從“小端”開始 好席怪?呢。

“大端“ ”小端” 各有優(yōu)點(diǎn)纤控,同吃雞蛋方式一樣挂捻,世人都有各自選擇的權(quán)利。

目前我們常見的CPU PowerPC船万、IBM是大端模式刻撒,x86是小端模式骨田。ARM既可以工作在大端模式,也可以工作在小端模式声怔,一般ARM都默認(rèn)是小端模式态贤。一般通訊協(xié)議都采用的是大端模式。

另外醋火,常見文件的字節(jié)序如下:

BMP – Little Endian

GIF – Little Endian

JPEG – Big Endian

RTF – Little Endian

Adobe PS – Big Endian

DXF(AutoCAD) – Variable

所以我們只有理解“大端”“小端”悠汽,才能在跨平臺、跨芯片芥驳、跨系統(tǒng)柿冲,跨網(wǎng)絡(luò)通信時,實(shí)時對內(nèi)存字節(jié)序進(jìn)行檢查和轉(zhuǎn)換兆旬,保證傳遞內(nèi)容的正確性假抄。假設(shè)沒有操作系統(tǒng)工程師,網(wǎng)絡(luò)工程師在背后默默對字節(jié)序的檢查和轉(zhuǎn)換丽猬,可能你用你的X86機(jī)器通過QQ給我PowerPC機(jī)器QQ表了個白慨亲,但數(shù)據(jù)在內(nèi)存中傳遞亂的yipi,消息到了以后宝鼓,前言不搭后語刑棵,我都完全不知道你想說什么,也不知道你在表白愚铡,彼此完美錯過是結(jié)局蛉签。

4> 通過C代碼檢測當(dāng)前計算機(jī)環(huán)境采用的是大端模式還是小端模式。

舉例:

方式一: 借助聯(lián)合體union的特性實(shí)現(xiàn)(union 型數(shù)據(jù)所占的空間等于其最大的成員所占的空間沥寥,對 union 型的成員的存取都是相對于該聯(lián)合體基地址的偏移量為 0 處開始碍舍,也就是聯(lián)合體的訪問不論對哪個變量的存取都是從 union 的首地址位置開始。)

#include <stdio.h>
int main()
{
    union{
        int a;  //4 bytes
        char b; //1 byte
    } data;

    data.a = 1;

    //b等于取a的低地址字節(jié)部分 
    if(data.b == 1){
        printf("Little_Endian\n");
    }else{
        printf("Big_Endian\n");
    }
    return 0;
}

說明:

賦值 1 是數(shù)據(jù)的低字節(jié)位(0x00000001)邑雅。

如果 1 被存儲在 data所占內(nèi)存 的低地址中片橡,那data.b 的值將會是 1。就是小端模式淮野,

如果 1 被存儲在 data所占內(nèi)存 的高地址中捧书,那data.b 的值將會是 0。就是大端模式骤星,

方式二: 通過將int強(qiáng)制類型轉(zhuǎn)換成char單字節(jié)经瓷,判斷起始存儲位置內(nèi)容實(shí)現(xiàn)。

#include <stdio.h>
int main()
{
    int a = 1; //4 bytes

    //b等于取a的低地址字節(jié)部分 
    char *b =(char *)&a;
    if (*b == 1)
    {
            printf("Little_Endian!\n");
    }
    else
    {
           printf("Big_Endian!\n");
    }
    return 0;
}

說明:

賦值 1 是數(shù)據(jù)的低字節(jié)位(0x00000001)洞难。

如果 1 被存儲在 a所占內(nèi)存 的低地址中舆吮,那b的值將會是 1。就是小端模式,

如果 1 被存儲在 a所占內(nèi)存 的高地址中色冀,那b的值將會是 0潭袱。就是大端模式,

——————————

5>End.PS:網(wǎng)上有很多锋恬,用MSB和LSB講大端和小端的描述屯换,我們一定需要注意,大端和小端描述的是字節(jié)之間的關(guān)系伶氢,而MSB趟径、LSB描述的是Bit位之間的關(guān)系。字節(jié)是存儲空間的基本計量單位癣防,所以通過高位字節(jié)和低位字節(jié)來理解大小端存儲是最為直接的蜗巧。

MSB:Most Significant Bit ------- 最高有效位(指二進(jìn)制中最高值的比特)

LSB:Least Significant Bit ------- 最低有效位(指二進(jìn)制中最高值的比特)

當(dāng)然,也可以通過MSB/LSB實(shí)現(xiàn)大端小端的檢測蕾盯,舉例代碼如下:

#include <stdio.h>

int main(void)
{
    union {
        struct {
            char a:1; //定義位域?yàn)?1 bit[不知位域何物幕屹,還請先自行查閱一下,后續(xù)文章也會專門講到] 
        } s;
        char b;
    } data;

    data.b = 8; //8(Decimal) == 1000(Binary)级遭,MSB is 1望拖,LSB is 0

    if (data.s.a == 1) //說明是MSB被存儲在高地址地址中
        printf("Big_Endian\n");
    else
        printf("Little_Endian\n");
    return 0;
}

From:【程序員秘書】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市挫鸽,隨后出現(xiàn)的幾起案子说敏,更是在濱河造成了極大的恐慌,老刑警劉巖丢郊,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盔沫,死亡現(xiàn)場離奇詭異,居然都是意外死亡枫匾,警方通過查閱死者的電腦和手機(jī)架诞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來干茉,“玉大人谴忧,你說我怎么就攤上這事〗浅妫” “怎么了沾谓?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長上遥。 經(jīng)常有香客問我搏屑,道長,這世上最難降的妖魔是什么粉楚? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上模软,老公的妹妹穿的比我還像新娘伟骨。我一直安慰自己,他們只是感情好燃异,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布携狭。 她就那樣靜靜地躺著,像睡著了一般回俐。 火紅的嫁衣襯著肌膚如雪逛腿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天仅颇,我揣著相機(jī)與錄音单默,去河邊找鬼。 笑死忘瓦,一個胖子當(dāng)著我的面吹牛搁廓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耕皮,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼境蜕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凌停?” 一聲冷哼從身側(cè)響起粱年,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罚拟,沒想到半個月后台诗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舟舒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年拉庶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秃励。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡氏仗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出夺鲜,到底是詐尸還是另有隱情皆尔,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布币励,位于F島的核電站慷蠕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏食呻。R本人自食惡果不足惜流炕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一澎现、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧每辟,春花似錦剑辫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挠将,卻和暖如春胳岂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舔稀。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工乳丰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镶蹋。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓成艘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贺归。 傳聞我的和親對象是個殘疾皇子淆两,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 由于某個問題,最近突然聯(lián)想到大端小端問題拂酣,時間久遠(yuǎn)秋冰,記憶有點(diǎn)模糊,所以又重新翻看了一下婶熬,做個記錄剑勾,內(nèi)容大都來源偉大...
    leehm閱讀 1,779評論 0 0
  • 本文包括2部分內(nèi)容:“ASCII虽另,Unicode和UTF-8” 和 “Big Endian和Little Endi...
    半島夏天閱讀 2,474評論 0 1
  • 1、概念 字節(jié)序饺谬,又稱端序捂刺,英文名稱Endianness。字節(jié)序是指存放多字節(jié)(byte)數(shù)據(jù)的順序募寨。多用于整數(shù)在...
    猿二胖閱讀 2,534評論 0 0
  • 大小端介紹問題總結(jié) 一族展、簡介大小端定義 大端模式所謂的大端模式,是指數(shù)據(jù)的低位(就是權(quán)值較小的后面那幾位)保存在內(nèi)...
    遇銀閱讀 1,348評論 3 1
  • 表情是什么拔鹰,我認(rèn)為表情就是表現(xiàn)出來的情緒仪缸。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了列肢,難過就哭了恰画。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,328評論 2 7