摘要:外部設(shè)備會(huì)自己處理字節(jié)序的問(wèn)題。本地序和網(wǎng)絡(luò)序從前面對(duì)于字節(jié)序的介紹可以知道采用小端序,而等采用大端序。協(xié)議很好的解決了這個(gè)問(wèn)題,協(xié)議規(guī)定使用大端字節(jié)序作為網(wǎng)絡(luò)字節(jié)序。提供了一組接口用于整型數(shù)據(jù)在本地序和網(wǎng)絡(luò)序之間的轉(zhuǎn)換。
我們學(xué)習(xí)了整型在內(nèi)存中是以原反補(bǔ)碼的形式存儲(chǔ)的,我們還學(xué)習(xí)了浮點(diǎn)型在內(nèi)存中是以符號(hào)位(S)指數(shù)位(E)有效數(shù)字(M)的形式存儲(chǔ)的。
那么我們知道了數(shù)據(jù)在內(nèi)存中是以什么樣的形式存儲(chǔ)的,可是我們知道內(nèi)存中有高地址有低地址,數(shù)據(jù)是一個(gè)字節(jié)分配一個(gè)地址,可是僅
char
類(lèi)型是一個(gè)字節(jié),其他類(lèi)型大都大于一個(gè)字節(jié)的大小,那么大于一個(gè)字節(jié)的數(shù)據(jù)是從【高地址】往【低地址】存放還是從【低地址】往【高地址】存放呢?
舉一個(gè)栗子?:當(dāng)你聲明一個(gè)變量的時(shí)候,操作系統(tǒng)會(huì)給你分配一塊空間,但是如果你創(chuàng)建的這個(gè)變量的類(lèi)型是【short/int/float/double】這些大小大于一個(gè)字節(jié)的類(lèi)型的數(shù)據(jù),操作系統(tǒng)反正是已經(jīng)把這些類(lèi)型相應(yīng)的大小的空間分配給你了,你內(nèi)部怎么存儲(chǔ)可不關(guān)它的事了,也就是我們將一個(gè)4字節(jié)的數(shù)據(jù)存入分配好的一段4字節(jié)的物理容器里, 該怎么存放呢?這時(shí),我們存放進(jìn)去的數(shù)據(jù)的字節(jié)是該依據(jù)一般人們的讀寫(xiě)習(xí)慣從左往右依次寫(xiě)入, 還是從右向左寫(xiě)入呢? 不論哪種方式只要保證寫(xiě)入和讀出的數(shù)據(jù)一致即可。
對(duì)于字節(jié)序列的存儲(chǔ)格式,必然需要說(shuō)到CPU的兩大派系,那就是IBM的Power PC系列的CPU和Intel的x86系列的CPU。Power PC系列采用big endian方式存儲(chǔ)數(shù)據(jù),而x86系列則采用little endian方式存儲(chǔ)數(shù)據(jù)。那么big endian和little endian都是些什么鬼呢??
在幾乎所有的機(jī)器上,多字節(jié)對(duì)象都被存儲(chǔ)為連續(xù)的字節(jié)序列,而字節(jié)序指的是多字節(jié)的數(shù)據(jù)各字節(jié)在內(nèi)存中的存儲(chǔ)順序,分為大端存儲(chǔ)模式(Big-Endian)和小端存儲(chǔ)模式(Little-Endian)。
假設(shè),一個(gè)4字節(jié)的int類(lèi)型變量a,它的十六進(jìn)制形式為0x11223344,(0x11
為高位字節(jié),0x44
為低位字節(jié))操作系統(tǒng)分配的空間的起始地址為0x000001,那么a的四個(gè)字節(jié)將被分別存在0x000001,0x000002,0x000003,0x000004的位置。
顯然,Big-Endian的存儲(chǔ)更貼切于我們平時(shí)的讀寫(xiě)習(xí)慣。那么為什么不統(tǒng)一使用Big-Endian呢?
計(jì)算機(jī)電路先處理低位字節(jié),效率比較高,因?yàn)橛?jì)算都是從低位開(kāi)始的,所以,計(jì)算機(jī)的內(nèi)部處理都是小端字節(jié)序。
而大端序存儲(chǔ),由于符號(hào)位在高位,因此對(duì)于數(shù)據(jù)正負(fù)或大小的判斷也就方便許多。另外,大端序也更符合人們的讀寫(xiě)習(xí)慣。所以,除了計(jì)算機(jī)的內(nèi)部處理,其他的場(chǎng)合幾乎都是大端字節(jié)序,比如網(wǎng)絡(luò)傳輸和文件儲(chǔ)存。
這里需要注意?:只有讀取的時(shí)候,才必須區(qū)分字節(jié)序,其他情況都不用考慮。
處理器讀取外部數(shù)據(jù)的時(shí)候,必須知道數(shù)據(jù)的字節(jié)序,將其轉(zhuǎn)成正確的值。然后,就正常使用這個(gè)值,完全不用再考慮字節(jié)序。即使是向外部設(shè)備寫(xiě)入數(shù)據(jù),也不用考慮字節(jié)序,正常寫(xiě)入一個(gè)值即可。外部設(shè)備會(huì)自己處理字節(jié)序的問(wèn)題。
從前面對(duì)于字節(jié)序的介紹可以知道x86采用小端序,而Power Pc等采用大端序。那么顯然不同的處理器體系,采用的字節(jié)序可能是不同的。那么如此一來(lái),不同機(jī)器之間的數(shù)據(jù)傳輸豈不是會(huì)出現(xiàn)問(wèn)題?
本地序(也稱(chēng)主機(jī)序):指處理器本身所采用的字節(jié)序,因此有的大端序,有的小端序。
網(wǎng)絡(luò)序:指網(wǎng)絡(luò)傳輸采用的字節(jié)序。網(wǎng)絡(luò)序是標(biāo)準(zhǔn)化的,統(tǒng)一采用大端序。因此,發(fā)送網(wǎng)絡(luò)數(shù)據(jù)之前需要將本地序轉(zhuǎn)換為網(wǎng)絡(luò)序。
為什么要注意本地序和網(wǎng)絡(luò)序的問(wèn)題呢?當(dāng)然,如果你寫(xiě)的程序只在單機(jī)環(huán)境下面運(yùn)行,并且不和別人的程序打交道,那么你完全可以忽略字節(jié)序的存在。但是,你的程序是要跟別人的程序產(chǎn)生交互的!
計(jì)算機(jī)網(wǎng)絡(luò)的出現(xiàn)讓大小端問(wèn)題變的復(fù)雜化了,每個(gè)計(jì)算機(jī)都有自己的主機(jī)字節(jié)序。不同計(jì)算機(jī)之間通過(guò)網(wǎng)絡(luò)通信時(shí):我“說(shuō)”的你聽(tīng)不懂,你“說(shuō)”我也聽(tīng)不懂,這可怎么辦?這時(shí)候就需要約定俗成的協(xié)議來(lái)解決問(wèn)題。
TCP/IP協(xié)議很好的解決了這個(gè)問(wèn)題,TCP/IP協(xié)議規(guī)定使用“大端”字節(jié)序作為網(wǎng)絡(luò)字節(jié)序。
這樣不管計(jì)算機(jī)采用哪種字節(jié)序,發(fā)送數(shù)據(jù)的時(shí)候必須將自己的主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序,對(duì)接收到的數(shù)據(jù)轉(zhuǎn)換為自己的主機(jī)字節(jié)序。這樣一來(lái),也就達(dá)到了與CPU、操作系統(tǒng)無(wú)關(guān),實(shí)現(xiàn)了網(wǎng)絡(luò)通信的標(biāo)準(zhǔn)化。
數(shù)據(jù)從本地傳輸?shù)骄W(wǎng)絡(luò),需要轉(zhuǎn)換為網(wǎng)絡(luò)序,接收到的網(wǎng)絡(luò)數(shù)據(jù)需要轉(zhuǎn)換為本地序后使用。C提供了一組接口用于整型數(shù)據(jù)在本地序和網(wǎng)絡(luò)序之間的轉(zhuǎn)換。
通信時(shí)的本地序和網(wǎng)絡(luò)序之間相互轉(zhuǎn)換這種常用的操作在Socket API這一層,一般都提供了封裝好的轉(zhuǎn)換函數(shù)。從主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換函數(shù):htons、htonl(C語(yǔ)言),從網(wǎng)絡(luò)字節(jié)序到主機(jī)字節(jié)序的轉(zhuǎn)換函數(shù):ntohs、ntohl(C語(yǔ)言)。當(dāng)然,明白了原理后也可以編寫(xiě)自己的轉(zhuǎn)換函數(shù)。
請(qǐng)簡(jiǎn)述大端字節(jié)序和小端字節(jié)序的概念,設(shè)計(jì)一個(gè)小程序來(lái)判斷當(dāng)前機(jī)器的字節(jié)序(百度筆試題)
思路:假設(shè)給上int a = 1;
1在內(nèi)存中16進(jìn)制表示形式為0x 00 00 00 01
,那么這段數(shù)據(jù)如果按大小端放置:
大端:00 00 00 01
小端:01 00 00 00
可以看出,可以通過(guò)判斷第一個(gè)字節(jié)的內(nèi)容判斷大小端,第一個(gè)字節(jié)為0則是大端,為1則是小端。
可是怎么取第一個(gè)字節(jié)呢?這里我們可以用指針的類(lèi)型的解引用來(lái)控制訪(fǎng)問(wèn)內(nèi)存的大小,char*
就是只訪(fǎng)問(wèn)一個(gè)字節(jié)的內(nèi)存。
int main(void){ int a = 1; char* p = (char*)&a; if (*p == 1) printf("小端"); else printf("大端"); return 0;}
把這個(gè)功能封裝成一個(gè)函數(shù):
int check_system(){ int a = 1; char* p = (char*)&a; if (*p == 1) return 1;//返回1,小端 else return 0;//返回0,大端}
那么這個(gè)函數(shù)呢,是可以?xún)?yōu)化的:
int check_system(){ int a = 1; char* p = (char*)&a; return *p; }
仍可以更簡(jiǎn)潔:
int check_system(){ int a = 1; return *(char*)&a;}
總結(jié):訪(fǎng)問(wèn)內(nèi)存就需要考慮到指針。
#include int main(){ int a = 0x11223344; char *pc = (char*)&a; *pc = 0; printf("%x/n", a); return 0;}
假設(shè)a變量的地址為0x64,則a變量在內(nèi)存中的模型為:
char*類(lèi)型的指針變量pc只能指向字符類(lèi)型的空間,如果是非char類(lèi)型的空間,必須要將該空間的地址強(qiáng)轉(zhuǎn)為char*類(lèi)型。
pc實(shí)際指向的是整形變量a的空間,即pc的內(nèi)容為0x64,即44;*pc=0,即將44位置中內(nèi)容改為0,修改完成之后,a中內(nèi)容為:0x11223300
(全劇終)感謝食用!
注:參考文章(https://www.ruanyifeng.com/blog/2016/11/byte-order.html)
|
|(系列持續(xù)周更)
|
數(shù)據(jù)存儲(chǔ)系列往期回顧:
詳解浮點(diǎn)型在內(nèi)存中的存儲(chǔ)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/119678.html
摘要:在位機(jī)器上,指針變量的大小為個(gè)字節(jié)。指針類(lèi)型的強(qiáng)制類(lèi)型轉(zhuǎn)換對(duì)指針變量進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換的一般形式將保存的類(lèi)型指針強(qiáng)制轉(zhuǎn)換為類(lèi)型指針后賦值給,其中還是為,沒(méi)有改變。 前言 大家好,我是努力學(xué)習(xí)的少年,今天這篇文章是專(zhuān)門(mén)寫(xiě)關(guān)于指針的知識(shí)點(diǎn),因?yàn)橹羔槂?nèi)容比較多,所以我將指針的這篇文章我將它分為...
摘要:數(shù)據(jù)的存儲(chǔ)前言數(shù)據(jù)類(lèi)型匯總整型家族浮點(diǎn)型家族自定義類(lèi)型指針類(lèi)型。整型家族注在之后的標(biāo)準(zhǔn)規(guī)定,將類(lèi)型數(shù)據(jù)劃分為整型家族,因?yàn)樽址趦?nèi)存中會(huì)將其轉(zhuǎn)化為碼值進(jìn)行存儲(chǔ)。 ...
摘要:寫(xiě)在前面博客主頁(yè)的江湖背景的江湖背景歡迎關(guān)注點(diǎn)贊收藏留言本文由原創(chuàng),首發(fā)首發(fā)時(shí)間年月日最新更新時(shí)間年月日?qǐng)?jiān)持和努力一定能換來(lái)詩(shī)與遠(yuǎn)方向未見(jiàn)花聞學(xué)習(xí)參考書(shū)籍深入理解計(jì)算機(jī)系統(tǒng)作者水平很有限,如果發(fā)現(xiàn)錯(cuò)誤,請(qǐng)留言轟炸哦萬(wàn)分感謝感謝感謝 ?寫(xiě)在前面 ?博客主頁(yè):kikoking的江湖背景?...
摘要:什么是字節(jié)序字節(jié)序,顧名思義就是字節(jié)的順序。因此,單字節(jié)的數(shù)據(jù)如或的類(lèi)型的數(shù)據(jù)沒(méi)有字節(jié)序這一說(shuō),因?yàn)楂@取它只需要讀取一個(gè)字節(jié)。主機(jī)序機(jī)器的字節(jié)序,有大端模式也有小端模式,根據(jù)具體機(jī)器的處理決定的,小端模式較常見(jiàn)。 1、什么是字節(jié)序 字節(jié)序,顧名思義就是字節(jié)的順序。更具體的講,它是多字節(jié)數(shù)據(jù)存儲(chǔ)和傳輸時(shí),字節(jié)的順序。 2、為什么有字節(jié)序這個(gè)東西? 因?yàn)槲锢韮?nèi)存是以字節(jié)為單位進(jìn)行數(shù)據(jù)存儲(chǔ),...
閱讀 4376·2021-09-09 09:33
閱讀 2381·2019-08-29 17:15
閱讀 2370·2019-08-29 16:21
閱讀 972·2019-08-29 15:06
閱讀 2613·2019-08-29 13:25
閱讀 578·2019-08-29 11:32
閱讀 3247·2019-08-26 11:55
閱讀 2587·2019-08-23 18:24