溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C語(yǔ)言之大小端問(wèn)題

發(fā)布時(shí)間:2020-06-25 16:30:23 來(lái)源:網(wǎng)絡(luò) 閱讀:1057 作者:菜鳥(niǎo)養(yǎng)成記 欄目:編程語(yǔ)言

1:大小端名字的由來(lái)及發(fā)展

  (1)在喬納森·斯威夫特的著名諷刺小說(shuō)《格列夫游記》中,小人國(guó)內(nèi)部分裂成Big-endian和Little-endian兩派,區(qū)別在于一派要求從雞蛋的大頭把雞蛋打破,另一派要求從雞蛋的小頭把雞蛋打破。斯威夫特借以諷刺英國(guó)的政黨之爭(zhēng),在計(jì)算機(jī)工業(yè)中指數(shù)據(jù)儲(chǔ)存順序的分歧。

     (2)后來(lái)計(jì)算機(jī)通信發(fā)展起來(lái)后,遇到一個(gè)問(wèn)題就是:在串口等串行通信中,一次只能發(fā)送1個(gè)字節(jié)。這時(shí)候我要發(fā)送一個(gè)int類型的數(shù)就遇到一個(gè)問(wèn)題。int類型有4個(gè)字節(jié),我是按照:byte0 byte1 byte2 byte3這樣的順序發(fā)送,還是按照byte3 byte2 byte1 byte0這樣的順序發(fā)送。規(guī)則就是發(fā)送方和接收方必須按照同樣的字節(jié)順序來(lái)通信,否則就會(huì)出現(xiàn)錯(cuò)誤。這就叫通信系統(tǒng)中的大小端模式。這是大小端這個(gè)詞和計(jì)算機(jī)掛鉤的最早問(wèn)題。

  (3)現(xiàn)在我們講的這個(gè)大小端模式,更多是指計(jì)算機(jī)存儲(chǔ)系統(tǒng)的大小端。在計(jì)算機(jī)內(nèi)存/硬盤(pán)/Nnad中。因?yàn)榇鎯?chǔ)系統(tǒng)是32位的,但是數(shù)據(jù)仍然是按照字節(jié)為單位的。于是乎一個(gè)32位的二進(jìn)制在內(nèi)存中存儲(chǔ)時(shí)有2種分布方式:高字節(jié)對(duì)應(yīng)高地址(大端模式)、高字節(jié)對(duì)應(yīng)低地址(小端模式)

   (4)現(xiàn)實(shí)的情況就是:有些CPU公司用大端(譬如C51單片機(jī));有些CPU用小端(譬如ARM)。(大部分是用小端模式,大端模式的不算多)。于是乎我們寫(xiě)代碼時(shí),當(dāng)不知道當(dāng)前環(huán)境是用大端模式還是小端模式時(shí)就需要用代碼來(lái)檢測(cè)當(dāng)前系統(tǒng)的大小端。

2:測(cè)試機(jī)器大小端模式的測(cè)試代碼

2.1:使用union來(lái)測(cè)試機(jī)器的大小端

#include<stdio.h>
union myunion
{
    int a;
    char b;
};

int little_or_big(void)
{
    myunion u1;
    u1.a = 1;
    return u1.b;
}
int main(void)
{
    int i = little_or_big();
     if(1==i)
    {
        printf("小端模式");
    }
    else
    {
        printf("大端模式");
    }
    return 0;
}

分析:

  首先共用體元素a和b在訪問(wèn)時(shí)候都是從低地址開(kāi)始訪問(wèn)的,u1.a = 1在內(nèi)存中的存放有兩種可能(內(nèi)存地址從左到右遞減),小端模式為 00  00 00 01;大端模式為: 01 00 00 00 ,而共用體u1中的b是char類似,所以我們用u1.b去訪問(wèn)時(shí)只能讀取到最低地址的值(按char去解析時(shí)只會(huì)讀取一個(gè)字節(jié)),所以,如果讀出u1.b的值為1則說(shuō)明當(dāng)前機(jī)器是小端模式,讀出u1.b的值為0,則說(shuō)明當(dāng)前機(jī)器是大端模式(這種測(cè)試方法要記住,面試時(shí)候經(jīng)??迹?/span>

2.2:指針?lè)绞絹?lái)測(cè)試大小端

int little_or_big2(void)
{
    int a = 1;
    char  b = *((char *) &a);
    return b;
}

分析:

  首選定義變量a= 1,然后將a的指針強(qiáng)制類型轉(zhuǎn)換成char *接著去解應(yīng)用這個(gè)指針,并賦值給b,然后根據(jù)b的返回值來(lái)確定大小端。其實(shí)分析可以發(fā)現(xiàn)其本質(zhì)都是一樣的,都是先給一個(gè)內(nèi)存里面存一個(gè)char 類型的1,然后使得另一個(gè)char 類型的變量b去讀取這個(gè)內(nèi)存的值,然后根據(jù)讀取的值來(lái)判斷大小端。

3:看似可行但實(shí)際不行的大小端測(cè)試方法

注:測(cè)試方法將測(cè)試代碼分別放在kile4.0(大端)和gcc(小端)下面去運(yùn)行,看運(yùn)行后的結(jié)果。

3.1:位運(yùn)算

理論分析:

  現(xiàn)在將0x1(0001)和0xf(1111)相與假設(shè)機(jī)器是大端模式,那么相與之后得到的結(jié)果是0001;假設(shè)機(jī)器是小端模式那么相與之后得到的結(jié)果是1000,

實(shí)際測(cè)試:

  理論可行但實(shí)際上不行的,原因是位與運(yùn)算是編譯器提供的運(yùn)算,這個(gè)運(yùn)算是高于內(nèi)存層次的(或者說(shuō)&運(yùn)算在二進(jìn)制層次具有可移植性,也就是說(shuō)&的時(shí)候一定是高字節(jié)&高字節(jié),低字節(jié)&低字節(jié),和二進(jìn)制存儲(chǔ)無(wú)關(guān))

3.2:移位

理論分析:

  同上假設(shè)的大端模式,那么存儲(chǔ)的方式是0001,右移1位則把 1 移出去了,所以得到的結(jié)果就是0x0;假設(shè)是小端模式,那么存儲(chǔ)方式是1000,右移1位,則結(jié)果是0100

實(shí)際測(cè)試:

   實(shí)際不行,原因同上因?yàn)镃語(yǔ)言對(duì)運(yùn)算符的級(jí)別是高于二進(jìn)制層次的。右移運(yùn)算永遠(yuǎn)是將低字節(jié)移除,而和二進(jìn)制存儲(chǔ)時(shí)這個(gè)低字節(jié)在高位還是低位無(wú)關(guān)的。

3.3:強(qiáng)制類型轉(zhuǎn)換

這里就不再次分析, 實(shí)際測(cè)試時(shí)不行的,原因同上






向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI