吃雞蛋引發的血案,詳解記憶體中的位元組序

2021-09-11 02:59:55 字數 2087 閱讀 7890

傳送門: 柏鏈專案學院

我們曾經看過乙個饅頭引發的血案,那麼吃雞蛋也能引發血案嗎?確實能!英國作家喬納森·斯威夫特的《格列弗遊記》當中就記載了這樣的故事!

這是一場由於吃雞蛋引發的戰爭,戰爭開始是由於以下的原因:我們大家都認為,吃雞蛋前,原始的方法是打破雞蛋較大的一端。可是當今皇帝的祖父小時候吃雞蛋,一次按古法打雞蛋時碰巧將乙個手指弄破了,因此他的父親,當時的皇帝,就下了一道敕令,命令全體臣民吃雞蛋時打破雞蛋較小的一端,違令者重罰。老百姓們對這項命令極為反感。歷史告訴我們,由此曾發生過六次叛亂,其中乙個皇帝送了命,另乙個丟了王位…關於這一爭端,曾出版過幾百本大部著作,不過大端派的書一直是受禁的,法律也規定該派的任何人不得做官。

當然上述只是乙個段子,吃雞蛋的問題不會影響那麼大,作者更多的是為了影射現實中因為很小的事情爆發大衝突的現象,比如天主教和新教之間的爭鬥!在it世界,同樣存在類似的問題。我們都知道資料以位元組形勢儲存,但是同樣的一段記憶體區域儲存相同的資料也是有兩個選擇的,因為記憶體位址有高有低之分,這就很像是吃雞蛋的問題了。下圖展示了2種選擇,第一種是將高位資料存放在低位址,低位資料存放在高位址,這比較符合人們讀資料從左到右的習慣,我們把這種方式叫大端法(bigendion);還有一種方式是將低位資料存放在低位址,高位資料存放在高位址,我們把這種方式叫小端法(littendtion)。

有童鞋一定會說,出現2種選擇,一定很麻煩的,為什麼不能統一呢?小端法和大端法確實都存在,例如在網路裝置中就按照大端法的方式去識別,而在很多pc機器當中卻是按照小端法去識別,這就給我們程式設計增加了麻煩。作為程式設計師知道原理肯定是可以解決的!

按照正常邏輯,我們心中應該產生2個問題:第乙個問題是我們使用的電腦是大端還是小端法?第二個問題是如何避免多平台多主機間互動沒有問題?

先來說第乙個問題,這個很好驗證的!我們只需要驗證一下記憶體位址中低位存放的是低位資料還是高位資料就可以了!這個對於c程式設計師比較擅長,可以借助c語言的union特性來判斷。

#include int main()

s; s.a = 0x0102;

//printf("buf[0]=%d,buf[1]=%d\n",s.buf[0],s.buf[1]);

if(s.buf[0] == 0x01) else

return 0;

}

因為union聯合體內的兩個元素共用相同的首位址,這樣a和buf可以認為在同一塊記憶體區域上。如果a(258)是0x0102,那麼就要看buf[0]和buf[1]內存放的是什麼資料?如果buf[0]是01就代表低位位址存放高位資料,這是大端,反之就是小端了!本機測試效果如下:

localhost:test yk$ gcc bigend.c -o bigend

localhost:test yk$ ./bigend

the system is littlendion

c語言作為更面向底層的語言,處理的肯定是更多的細節,如果是更為偏向應用層的語言,或許不知道這麼多也沒問題。在go語言中,大端法和小端法的處理仍然需要知道。go語言為我們提供了轉碼用的"encoding/binary"包,提供了將數字轉換為byte陣列的方式,可以參看如下示例:

func inttohex(num int64) byte 

return buff.bytes()

}

inttohex函式可以按照大端法的形勢將資料轉化為byte陣列的形勢,這樣跨平台的時候統一按照大端法解析就可以了!說到這裡是不是發現,我們前面提出的第二個問題也解決了!整理一下思路就是資料傳輸時按照統一的編碼格式進行編碼,接收方再按照相同的方式去解碼就不會出現問題了。

如果使用c語言或go語言這種偏向底層的語言編寫網路程式,尤其是跨平台的情況下,一定要懂得大端和小端的原理,否則可能要吃大虧!

U Boot中巨集定義MK STR引發的「血案」

在編譯uboot的過程中,經常需要針對不同版本,修改波特率等相關引數。為了讓這個過程更加輕鬆和簡單 不用每次手工修改原始碼 於是將這些引數定義到menuconfig中,沒想到就是這個小小的動作,竟然導致了乙個奇怪的問題 編譯後的uboot無法啟動!這是怎麼一回事呢?各位看官別急,且聽我慢慢道來 由於...

詳解Java中的this關鍵字

使用this呼叫本類中的屬性 現在觀察以下 看會有那些問題 public void setname string name 這裡面的兩個name都是setname方法中的name引數。此時,特別希望可以通過乙個指定的標識明確的表示要把傳入的name引數的值給類中的屬性,所以此時就需要使用this關鍵...

詳解python中的with關鍵字

對於系統資源如檔案 資料庫連線 socket 而言,應用程式開啟這些資源並執行完業務邏輯之後,必須做的一件事就是要關閉 斷開 該資源。如何正確的關閉乙個檔案呢?1.普通版 def test0 f open 1.txt w f.write 0000 f.close 2.高階版 def test1 f ...