1. 程式人生 > >大端小端與數字的二進位制儲存

大端小端與數字的二進位制儲存

部分1:大端小端概念

摘自:https://jocent.me/2017/07/25/big-little-endian.html

計算機系統中記憶體是以位元組為單位進行編址的,每個地址單元都唯一的對應著1個位元組(8 bit)。這可以應對char型別資料的儲存要求,因為char型別長度剛好是1個位元組,但是有些型別的長度是超過1個位元組的(字串雖然是多位元組的,但它本質是由一個個char型別組成的類似陣列的結構而已),比如C/C++中,short型別一般是2個位元組,int型別一般4個位元組等。因此這裡就存在著一個如何安排多個位元組資料中各位元組存放順序的問題。正是因為不同的安排順序導致了大端儲存模式和小端儲存模式的存在。

1. 概述

1.1 定義

假如有一個4位元組的資料為 0x12345678(十進位制:305419896,0x12為高位元組,0x78為低位元組),若將其存放於地址 0x4000 8000中,則有:

記憶體地址0x4000 8000(低地址)0x4000 80010x4000 80020x4000 8003(高地址)
大端模式0x12(高位元組)0x34            0x560x78(低位元組)

小端模式0x78(低位元組)0x560x340x12(高位元組)

明顯可以看出規律,即大端“高低低高”,小端“高高低低”:

大端模式:是指資料的高位元組儲存在記憶體的低地址中,而資料的低位元組儲存在記憶體的高地址中

小端模式,是指資料的高位元組儲存在記憶體的高地址中,而資料的低位元組儲存在記憶體的低地址中

說明:0x代表16進位制,由於16為2的4次方,剛好可以用4位半個位元組表示;,或者說兩個16進位制數用一個位元組表示。所以對於16進位制的儲存可以說:一個16進位制數佔4位,或者說兩個16進位制數佔一個位元組。比如對於int 0x12345678,0x12、0x34、0x56、0x78各佔一個位元組,直接翻譯二進位制為0001、0010,0011、0100,0101、0110,0111、1111;這種翻譯方法與將0x12345678先轉為10進位制,再換算為二進位制結果一致。

1.2 特點
為什麼截然相反的大小端儲存模式能夠並存至今?在標準化備受推崇的今天,為什麼大小端誰都沒有被另外一個所同化?我想這除了歷史的慣性使然,還與它們各自的優缺點有關。

大端模式優點:符號位在所表示的資料的記憶體的第一個位元組中,便於快速判斷資料的正負和大小

小端模式優點:1. 記憶體的低地址處存放低位元組,所以在強制轉換資料時不需要調整位元組的內容(註解:比如把int的4位元組強制轉換成short的2位元組時,就直接把int資料儲存的前兩個位元組給short就行,因為其前兩個位元組剛好就是最低的兩個位元組,符合轉換邏輯); 2. CPU做數值運算時從記憶體中依順序依次從低位到高位取資料進行運算,直到最後重新整理最高位的符號位,這樣的運算方式會更高效

其各自的優點就是對方的缺點,正因為兩者彼此不分伯仲,再加上一些硬體廠商的堅持(見1.3節),因此在多位元組儲存順序上始終沒有一個統一的標準

1.3 現狀

Intel的80×86系列晶片使用小端儲存模式
ARM晶片預設採用小端,但可以切換為大端
MIPS晶片採用大端,但可以在大小端之間切換
在網路上傳輸的資料普遍採用的都是大端
2. 判斷

方法一:通過將多位元組資料強制型別轉換成單位元組資料,再通過判斷起始儲存位置是資料高位元組還是低位元組進行檢測

// @Ret: 大端,返回true; 小端,返回false
bool IsBigEndian_1()
{
    int nNum = 0x12345678;
    char cLowAddressValue = *(char*)&nNum;

    // 低地址處是高位元組,則為大端
    if ( cLowAddressValue == 0x12 )    return true;

    return false; 
}

方法二:利用聯合體union的存放順序是所有成員都從低地址開始存放這一特性進行檢測

// @Ret: 大端,返回true; 小端,返回false
bool isBigEndian_2()
{
    union uendian
    {
       int nNum;
       char cLowAddressValue;
    };

    uendian u;
    u.nNum = 0x12345678;
    
    if ( u.cLowAddressValue == 0x12 )     return true;

    return false;
}
3. 轉換

3.1 大小端轉換
// 實現16bit的資料之間的大小端轉換
#define BLSWITCH16(A)   (  ( ( (uint16)(A) & 0xff00 ) >> 8  )    | \  
                           ( ( (uint16)(A) & 0x00ff ) << 8  )     )  

// 實現32bit的資料之間的大小端轉換
#define BLSWITCH32(A)   (  ( ( (uint32)(A) & 0xff000000) >> 24) |\
         (((uint32)(A) & 0x00ff0000) >> 8) | \
         (((unit32)(A) & 0x0000ff00) << 8) | \
         (((uint32)(A) & 0x000000ff) << 32)  )

3.2 網路位元組序與主機位元組序的轉換

方法三:使用記憶體檢視器

轉自:https://blog.csdn.net/shuiniu1224/article/details/21997221

檢視記憶體是使用VS2010進行編碼的一個非常基本的技能了,快速而準確地檢視記憶體,可以幫助你準確分析程式碼中各變數的取值,以及儲存狀態,幫助你發現程式中的BUG,改進程式碼的健壯性。

如何檢視記憶體?繼續採用以上的例程進行說明,將程式F5到第13行,再單步到下一句


圖3

按下ALT+6,此時我們可以看到記憶體1的視窗,我們從自動視窗中先找到指標p的地址,然後將地址複製到記憶體位址列中,回車,即可看到此時地址中的值。記憶體視窗中左邊的灰色值代表地址,右邊則表示地址中儲存的值。我們可以看到p地址對應的值為03,但後面還有000000跟著,其實因為我們儲存的是一個整數值,需要4個位元組儲存,因此就算P中結果是3,也同樣佔用了4個位元組。

這裡還需要注意的一個概念是,大端法儲存和小端法儲存的概念。回到上面圖中我們可以看出,記憶體地址從左至右,從上至下是依次增大的。我們這個值3其實正確的讀法應該是從右至左讀取的,即0x00000003,03是在最低位,而03也是儲存在記憶體地址中的低地址中的,因此這是小端法儲存,大端法則剛好相反。需要了解這方面更多資訊的人,一定要上網查詢更多資料多學習,本文就不再詳述。


部分2:數字儲存與大端小端結合

例題1

union Aunion
{
	short k;
	char t[2];
}val;
int main()
{
	val.t[0] = 5;
	val.t[1] = 1;
	printf("%d", val.k);
	return 0;
}

輸出的值是多少?

5的二進位制為0000 0101,1二進位制為0000 0001,所以排列順序為0000 0101 0000 0001,(記憶體中:地址由小到大,並且每個地址單元都唯一的對應著1個位元組(8 bit))。若為小端,則val.k在取出時,5、1的二進位制被解釋為0000 0001 0000 0101,其10進位制數為261;若為大端,則val.k在取出時,5、1被解釋為0000 0101 0000 0001,位2861。

例題2

int main()
{
	char a = -1;
	unsigned char b = -1;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

求輸出到螢幕的數

首先明確整數的儲存方式:正整數直接儲存其二進位制形式,位數不夠時,在其二進位制數左邊補0;對於負整數,先求出其正數的二進位制,然後對此二進位制數求補碼即可。

所以對於-1計算方法為:

1的二進位制     :0000 0001

對上述求補碼:1111 1111

所以字元a、b都是儲存的1111 1111,由於a是有符號的char,故取1111 1111補碼,為0000 0001,輸出1;b是無符號的char,故輸出為1111 1111對應的數字255。

float、double的儲存方式:先將該數轉為對應的二進位制,在寫成二進位制對應的科學計數法,之後儲存該數的三部分資訊,分別是符號、指數、尾數(小數點後邊的數,小數點前邊的數必為1);

符號正為0,負為1,指數採用餘碼方式(使得沒有指數部分沒有複數)float為餘127碼(指數加上127),double為餘1023碼(指數加上11023),尾數部分可以看成是正整數的儲存方式;

float - 符號佔1位,指數佔8位,尾數佔23位,double - 符號佔1位,指數佔11位,尾數佔52位。

相關推薦

大端數字二進位制儲存

部分1:大端小端概念摘自:https://jocent.me/2017/07/25/big-little-endian.html計算機系統中記憶體是以位元組為單位進行編址的,每個地址單元都唯一的對應著1個位元組(8 bit)。這可以應對char型別資料的儲存要求,因為char

大端LSB和MSB的故事

這樣就可以顯而易見看出,大小端和LSB MSB本質區別是在排序的單位不同,在晶片中應當留意暫存器是否有LSB或者MSB的字樣,有的話應當對資料的序列進行改寫,這幾天就被這坑,坑了一段時間,因為之前一直沒有接觸過LSB和MSB,可是接觸過大小端的概念,先入為主的想法,讓我在一個簡單的問題困擾許久。現在才發現理論

大端堆、棧的生長方向聯系起來記憶

.cn 人類 方便 left 32位 images 順序 記憶 bsp 對於大端、小端的區別,可能看資料的時候確實理解了,但過段時間就搞混了;高位低地址、低位高地址、高位高地址、低位低地址...是不是看起來就好頭大,哪個對應哪個啊。其實可以把大小端與堆棧聯系起來記憶,雖

c語言 之大端儲存問題

我們都知道資料在計算機中的儲存是以補碼形式儲存的。在計算機中,如果資料的高位元組內容放在高地址處,低位元組內容放在低地址處,我們稱它為小端位元組序;相反,如果資料的高位元組內容放在底地址處,低位元組內

資料儲存大端的區別

大端模式,是指資料的高位元組儲存在記憶體的低地址中,而資料的低位元組儲存在記憶體的高地址中,這樣的儲存模式有點兒類似於把資料當作字串順序處理:地址由小向大增加,而資料從高位往低位放;這和我們的閱讀習慣一致。小端模式,是指資料的高位元組儲存在記憶體的高地址中,而資料的低位元組儲

大端模式簡單介紹 以及三種檢測大小儲存的方法

大端模式:是指資料的高位元組儲存在記憶體的低地址中,而資料的低位元組儲存在記憶體的高地址端。 小端模式,是指資料的高位元組儲存在記憶體的高地址中,低位位元組儲存在在記憶體的低地址端。 比

大端

vps .com msp430 jce -h 大端小端 小端 kdt aid 什麽是大端小端 所謂的大端模式,是指數據的低位保存在內存的高地址中,而數據的高位,保存在內存的低地址中; 所謂的小端模式,是指數據的低位保存在內存的低地址中,而數據的高位保存在內存的高地址中。 8

大端/,高字節/低字節,高地址/低地址,移位運算

地址 我愛你 沒有 字段 移動 就會 strong spa 消失 其實大端小端的概念比較好理解的,大端:數據的高字節存放在內存的低地址中。 數組的聲明方式是從左往右,地址逐漸增大。 int8_t a[] = { 1, 2, 3 };

大端總結

== lowest %x main lsb logs 2-2 小端 技術分享 大端(Big Endian)和 小端(Little Endian)在開發中經常會遇到的問題,因此在正式開發前,清楚的了解當前的開發環境是大端模式還是小端模式就顯得非常重要。 大端:指的是數據的最高

大端 和網絡字節序說明

body 地址 eve powerpc tcp ron 轉換成 字節流 n) 不同CPU存放數據有大端(Big-Endian)和小端(little-Endian)之分 小端字節序和大端字節序表示存儲的字節順序有區別 小端字節序:低字節存於內存低地址;高字節存於內存高地址;

大端/的存儲模式

() 內容 class void 二進制 表現 永遠 方式 指針 2017年11月23日大端/小端的存儲模式1.大端:   如果是將高字節的數據存儲在低地址,低字節數據存儲在高地址,這種存儲模式就是大端模式;2.小端:   如果是將高字節的數據存儲在高地址,低字節數據存儲在

記憶體地址、大端問題

記憶體地址 一個記憶體地址可儲存 8 bit = 1 byte(位元組) 32位作業系統可定址空間為 2^32 (Byte) = 2^10 * 2^10 * 2^10 *4 = 4 GB 資料所佔記憶體大小 C宣告 位元組數

初夏談:大小(測試當前機器是大端/

大小端:                大端儲存模式:就是記憶體的低地址上存著資料的高位,高地址上存著資料的低位。            

大端 和網路位元組序說明

大端(Big-Endian)和小端(little-Endian)的起源 關於大端小端名詞的由來,有一個有趣的故事,來自於Jonathan Swift的《格利佛遊記》:Lilliput和Blefuscu這兩個強國在過去的36個月中一直在苦戰。 戰爭的原因:大家都知道,吃雞蛋的時候,原始的方法是打破

輕鬆記住大端的含義(附對大端的解釋)

原文地址:http://www.cnblogs.com/wuyuegb2312/archive/2013/06/08/3126510.html   或許你曾經仔細瞭解過什麼是大端小端,也動手編寫了測試手頭上的機器上是大端還是小端的程式,甚至還編寫了大端小端轉換程式;但

大端 && 網路位元組序

(0)背景: 網路上的資料流是位元組流,對於一個多位元組數值,在進行網路傳輸的時候,先傳遞哪個位元組?也就是說,當接收端收到第一個位元組的時候,它是將這個位元組作為高位還是低位來處理呢?  (1)網路位元組序定義: 收到的第一個位元組被當作高位看待,這就要求傳送端傳送的第

CAN通訊物理層(取樣點、大端

        KEL15與KEL30存在電壓範圍的區別和功能上的區別:KEL30是指提供基本功能的供電電壓,功能很少:KEL15是指提供多功能的供電電壓。其中KEL15又稱:IG ON。        &nbs

網路位元組序 大端

1.小端法(Little-Endian)就是低位位元組排放在記憶體的低地址端(即該值的起始地址), 高位位元組排放在記憶體的高地址端; 2.大端法(Big-Endian)就是高位位元組排放在記憶體的低地址端(即該值的起始地址), 低位位元組排放在記憶體的高地址端;    

MSB LSB 大端 Big-Endian Small-Endian

MSB :Most   Significant   Bit LSB :Lest   Significant   Bit    在網路通訊方面,大家說的更多的 是:“Big-Endian”和“Small-Endian”的問題。     指的都是對於多位元組的資料型別(比如4位元組的32位整數),其多個

【轉】輕鬆記住大端的含義(附對大端的解釋)

 轉自:http://www.cnblogs.com/wuyuegb2312/archive/2013/06/08/3126510.html        或許你曾經仔細瞭解過什麼是大端小端,也動手編寫了測試手頭上的機器上是大端還是小端的程式,甚至還編寫了大端小端轉換程式;