編譯器和解釋器的區別

實例一:

 菜鳥經常將編譯器和解釋器弄混淆,無奈之下,於是向高手請教。

  高手說:

  解釋器是一條一條的解釋執行源語言。比如php,postscritp,javascript就是典型的解釋性語言。  

  編譯器是把源代碼整個編譯成目標代碼,執行時不在需要編譯器,直接在支持目標代碼的平臺上運行,這樣執行效率比解釋執行快很多。比如C語言代碼被編譯成二進制代碼(exe程序),在windows平臺上執行。

 

  菜鳥說:“我還是不明白,能給個形象的比喻麼?”

  高手說:“給你講個故事。”

  母親打電話給兒子說:“你爸最近身體不好,家裏人少不熱鬧”。

      兒子想,對啊,爸年紀大了,身體不好,買點犛牛骨髓壯骨粉不錯,於是兒子就去超市買了犛牛骨髓壯骨粉。

  兒子又想啊,最近黃金搭檔很火,買點給爸試試。於是兒子又去買了黃金搭檔。

  從超市回來後,兒子又尋思母親說的“家裏不熱鬧”,嗯,家裏的小皇帝自從上寄宿學校後就比較少回來,估計是老人家想孫子了。兒子於是給上高中的兒子打了個電話,讓他週末回來看看。

  

  母親打電話給女兒說:“你爸最近身體不好,家裏人少不熱鬧”。

  女兒就想,應該給爸做點什麼呢?於是她拿出張紙開始羅列條目,先寫上了壯骨粉和黃金搭檔。然後,想着讓老人家看看外孫應該不錯,於是就在紙上加上了一句,一家人回爸媽那裏看望看望。最後紙上就寫着:

  1.壯骨粉和黃金搭檔

  2.一家人去看望爸媽

      女兒見到女婿後,就將這張紙上的信息編成短信發給了工作的女婿。

  女婿一看就明白了,下班後先去超市買了補品,然後開車回家帶着妻兒就去看望岳父岳母了。

 

      想到什麼了嗎?

  菜鳥說:

  我這樣說不知道對不對:兒子就像是解釋器,是想到一點做一點。女兒就像編譯器,女婿就像平臺,女兒聽完後,在紙上羅列出所有要做的事情,女婿就按着指示辦事了。

  高手說:

  就是這樣的。兒子對於母親的話是一條一條執行,女兒是將母親的話整個翻譯成平臺能理解的目標語言--短信,整個由女婿直接執行。後者的執行效率會更高。

 

  從功能上看,解釋器和編譯器確實不一樣。

  然而,從流程和結構上看,二者卻非常相似。

  兒子和女兒聽到母親的話以後,都是從兩個方面來思考:老人的身體和老人對小輩的思念。以此爲據,兒子和女兒都做出了自己的決定。只不過一個直接去做了,另一個卻將所要做的事情翻譯成另一種載體--短信--給存儲起來。

      解釋器和編譯器也是如此,讀入源語言後,解釋器和編譯器都要進行詞法分析、語法分析和語義分析,之後,二者開始有所分別。解釋器在語義分析後選擇了直接執行語句;編譯器在語義分析後選擇將將語義存儲成某一種中間語言,之後通過不同的後端翻譯成不同的機器語言(可執行程序)。如下圖所示:

  總之,解析器和編譯器它們在功能上是不一樣的,然而從結構上看卻有諸多相同,而且在開發時也並沒有本質上的差別,這也是很多人將二者混淆的原因之一。究竟是開發解析器還是編譯器?只需要依據功能上的實際需要來做出決定就ok了。

 


實例二:

來福與旺財的養牛場

來福和旺財有一個養 牛場。本來養牛不是一件太難的事情,但是偏偏他倆養的牛都有特別的怪癖。奶牛阿圓只吃切成圓形的牧草,而奶牛阿方和阿三(印度來的?)分別只吃切成正方形 和三角形的牧草。如果來福和旺財拿不和奶牛性格的草去餵食,阿X們不但不產奶而且還會鄙視來福和旺財。

於是來福和旺財分別有了自己的主意

來福的方案:
來福發明了三套大型碾碎機:圓圓碾碎機,方方碾碎機和三三碾碎機。每天收割了牧草,就分別放到這三套機器裏碾碎給三頭奶牛吃。但是一旦被碾碎了,這堆草就只能給某一頭牛吃了。很明顯阿方是不會吃給阿圓準備的草的。而且來福每天都要操作這三臺機器,覺得比較麻煩。
點擊在新窗口中瀏覽此圖片


旺財的方案:
旺財在考察了來福的方案後,發現每天操作三臺機器真的很麻煩,而且有時有的牛吃不完,有的牛不夠吃時,還不能在奶牛之間調配碾碎了的牧草。所以旺財有了不同的想法:口罩型碾碎機。
點擊在新窗口中瀏覽此圖片

就像在圖上看到的,旺財給每頭奶牛裝配了一臺口罩碾碎機,所以三頭牛完全可以在一個槽裏吃草了,在吃之前口罩會自動把牧草碾碎成適合該牛食用的類型。旺財就輕鬆了,他每天只需要割割草就行了。

但是旺財被鄙視了???

是的,被來福鄙視了。來福觀察後發現,旺財的口罩碾碎機的效率很低(因爲比較小嘛)。阿圓食量大,吃來福的圓圓碾碎機的食物一個小時就飽了,但是戴着口罩吃的時候要吃十個小時!所以來福認爲旺財的口罩碾碎機雖然省事,但只能喂喂小牛,完全不適合食量大的牛。

旺財也覺得這樣做有問題,但他不想回到來福方案上,他改進了口罩方案:牧草預切割機。
點擊在新窗口中瀏覽此圖片

呵呵,看到預切割做了什麼嗎?它把牧草割得小了一些,所以需要口罩碾碎機做的事情就少多了。(當然口罩碾碎機也要作適當改進適合預切割後的牧草,所以圖上用藍色表示)阿圓以前用口罩不是要吃十個小時嗎,現在兩三個小時就可以了。

編譯器與解釋器

好的,謝謝你有耐心看到這裏,經過上面那個不太恰當的例子,相信你已經相當的糊塗了。那麼我們試着回到技術方面來。
在上面的例子中
牧草 = 我們的各種編程語言,C/C++/C#, Java, Pascal, PHP, Python, Perl, Java Script等等
切割機 = 各種編譯器
奶牛 = 各種CPU(不要告訴我Intel和AMD哦),比如x86,ARM,MIPS等等
那你應該知道了爲什麼奶牛會有吃不同形狀牧草的嗜好了,這個奇怪的比喻是爲了表示不同的CPU接受的不同的機器語言。

對應上面的奶牛圖,編譯器的圖是這樣的
點擊在新窗口中瀏覽此圖片


源代碼被編譯成機器碼,在CPU上運行。

而解釋器是這樣的
點擊在新窗口中瀏覽此圖片


用解釋器很方便,只需要直接“運行”就好了,不用像C那樣有編譯鏈接的工序。

爲什麼說這些語言是跨平臺的?因爲你寫了程序以後,如果這個平臺上有這種語言的解釋器,只需要拿到這個平臺上直接運行就可以了。你可以理解爲:解釋器是在“一邊編譯,一邊運行”,它只是把以前程序員手工做的編譯過程放在了運行程序的時候進行。

爲什麼我們一般說解釋器的效率比較低?你也可以想象的是,一段程序在解釋器中運行時可能會被編譯多次,因爲每次運行到這段程序時,都會重新編譯一次,這樣的開銷是很大的。

所以誕生了Java,C#這樣的預編譯語言:
點擊在新窗口中瀏覽此圖片

在運行之前,需要手動把源代碼編譯成中間代碼(Java裏叫字節碼),然後在解釋器中執行。
這種架構避免了上面純解釋器中編譯源代碼的開銷,所以相對會有效率一些。

但 是我不能騙你們,其實我畫在純解釋器中的Python,Perl,PHP可能都不會是真的純解釋執行的,這樣實在是太沒有效率。Python在運行時會生 成pyc的二進制臨時文件,看起來很像是預編譯的結果。只有JavaScript這種真的不會寫得太長的語言(Ajax請原諒我)纔會採用純解釋的運行方 式。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章