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