參考
https://zh.wikipedia.org/wiki/%E5%AD%97%E8%8A%82%E5%BA%8F
https://www.ruanyifeng.com/blog/2016/11/byte-order.html
https://blog.csdn.net/XiyouLinux_Kangyijie/article/details/72991235
字節順序,又稱端序或尾序(英語:Endianness),在計算機科學領域中,指存儲器中或在數字通信鏈路中,組成多字節的字的字節的排列順序。
在幾乎所有的機器上,多字節對象都被存儲為連續的字節序列。例如在C語言中,一個類型為int
的變量x
地址為0x100
,那么其對應地址表達式&x
的值為0x100
。且x
的四個字節將被存儲在存儲器的0x100, 0x101, 0x102, 0x103
位置。[1]
字節的排列方式有兩個通用規則。例如,一個多位的整數,按照存儲地址從低到高排序的字節中,如果該整數的最低有效字節(類似於最低有效位)在最高有效字節的前面,則稱小端序;反之則稱大端序。在網絡應用中,字節序是一個必須被考慮的因素,因為不同機器類型可能采用不同標准的字節序,所以均按照網絡標准轉化。
今天在調試的時候,突然想到了這個。結果發現,原理是知道,但是具體大小端是什么意思?網絡序是大端還是小端?如何判斷系統是否是大小端?發送網絡序的時候如何設置數據?都不能詳細的描述出來,所以寫一篇博客總結一下。
小端就是默認有效值所在的地址空間是初始地址(低地址),大端就是默認有效值所在的地址是高地址。這樣更好理解一些。
比如我們有一個int類型的數據,需要占用4個字節,那么如果保存一個1,這個1所在的位置是放到4個字節的哪一個呢?這必須要有一個統一的標准。小端的標准就是放到低地址,大端的就是放到高地址。
Windows系統在x86-64下是小端,我們定義一個整數為1,看一下內存,1放在了低地址。
第一個問題解決了,那么網絡序呢?網絡序使用的是大端標准。那么對我們有什么影響呢? 如果是同一平台(網絡傳輸雙方都是大端或是小端),雙方可以不用考慮大小端,直接發送接收就可以(當然這是不標准的)。因為數據發送就是發送,是一個數據流,abcdef發送過去,接收也是abcdef,數據沒有變化。但是如果不同的平台,比如abcdef在我的平台保存序列就是badcfe,那么發送就是badcfe,接收也是badcfe,如果是同一平台,那么我認為badcfe就是abcdef,那么是無所謂的,如果是不同平台,我認為badcfe是badcfe,那么數據就亂了。所以網絡字節序規定了一個標准,大家都按照這樣存儲,都按照這樣轉換,那么不同平台就可以互通了。比如小端abcdef在網絡字節序上是badcfe,如果是小端接收,那么獲得數據badcfe知道是大端,那么就轉換成自己的abcdef,大端系統接收到badcfe,同樣知道是大端,與自己一樣,就不需要轉換直接保存badcfe,也表示abcdef,這樣數據就沒有亂掉了。
最后一個問題就是,如何判斷系統是大端還是小端,如果知道原理,那么就簡單了
int a = 1; if (*((char*)&a) == 1) { cout << "little"; }
上面就是賦值1給a,a是一個int類型,占用4個字節,如果是小端,那么1應該先放到低地址;如果是大端,那么 1應該放到高地址。(char*)&a是把a的指針強轉成一個char的指針,那么默認指的位置也就是低地址,低地址的第一個字節如果保存的是1,那么就是小端,如果不是1,就是大端。