上一章我們已經(jīng)了解到,編程語言其實就是一種我們?nèi)祟愐子诶斫獾某绦蛘Z言。我們用這種編程語言編寫的程序就稱為源代碼。這些源代碼是通過翻譯器這么個東西,被翻譯成二進制指令,從而讓計算機能夠執(zhí)行我們的指令。
那么,這其中發(fā)揮很大作用的翻譯器又是怎么回事?
編譯型語言與解釋型語言
其實,翻譯器不止一種。我們根據(jù)翻譯器翻譯的時機,將它分為了編譯器和解釋器。
相應(yīng)的,編程語言也分為了編譯型語言和解釋型語言。
編譯型語言要求將所有的源代碼通過編譯器轉(zhuǎn)換成二進制指令,也就是生成一個可執(zhí)行程序(比如Windows下的.exe文件),比如匯編語言、C語言、C++等都是編譯型語言。
解釋型語言,顧名思義就是將源代碼一邊轉(zhuǎn)換,一邊執(zhí)行。就好像你閱讀文章一樣,讀到哪程序執(zhí)行到哪。這種方式不需要生成可執(zhí)行程序,使用會更加方便,比如Python、PHP、JavaScript、MATLAB等都是解釋型語言。
雖然文中對編譯器和解釋器講解的比較簡單,但事實上,翻譯源代碼的過程十分復(fù)雜,過程大致包括詞法分析、語法分析、語義分析、性能優(yōu)化、生成可執(zhí)行文件等5個步驟,其中涉及到復(fù)雜的算法和硬件架構(gòu),這一點本文不再贅述。
操作系統(tǒng)
另外大家需要了解的一點是,計算機程序都是運行在操作系統(tǒng)中的,目前我們比較熟知的操作系統(tǒng)平臺都有Windows、Linux、MacOS,當(dāng)然這三種操作系統(tǒng)都不是瞬間誕生的,也都經(jīng)歷了操作系統(tǒng)幾十年的發(fā)展,才完善成我們目前熟知的版本。
長時間不同發(fā)展,導(dǎo)致不同的操作系統(tǒng)平臺之間底層的內(nèi)部結(jié)構(gòu)截然不同,也就是說能夠在Windows系統(tǒng)運行的程序,拿到MacOS下便會無法運行,同理,能在Linux平臺下執(zhí)行的程序,也不能在Windows平臺下執(zhí)行。
另外,就算是相同的操作系統(tǒng),不同的版本之間也不一定兼容。比如不能將Windows64位程序拿到Windows32位平臺下運行。但反之一般都可以,這是因為64位Windows對32位程序做了兼容性處理。這也是幾乎所有程序版本之間的通病,新版本可以兼容老版本,老版本兼容不了新版本。
除了程序不能跨平臺使用之外,源代碼也不能跨平臺使用。例如C語言中,可以讓程序暫停的“睡眠”函數(shù),在Windows平臺下函數(shù)名是Sleep,但在Linux平臺下該函數(shù)名是sleep,首字母大小寫不同。而且函數(shù)中的參數(shù)含義也不同,Sleep的參數(shù)是毫秒,sleep的參數(shù)是秒。
這是一件相當(dāng)麻煩的事情,這意味著同一個軟件,你不僅需要開發(fā)3種不同的源代碼,還要生成3種平臺的可執(zhí)行程序,分別兼容Windows、Linux、Mac OS這3種平臺(現(xiàn)在大部分軟件都有不同操作系統(tǒng)下的版本就是因為這個原因),未來的更新維護也需要同時更新3個版本。而且,萬一以后新出來個鴻蒙操作系統(tǒng),是不是又需要從頭開發(fā)新的版本呢?
當(dāng)然,以程序員的勤勞度來看,是不會做出這么費力不討好的事情的。事實上,程序員有各種方法來解決這個問題。
比較經(jīng)典的辦法,就是開發(fā)一套支持跨平臺的語言。誕生于1995年的Java就是其中的引領(lǐng)者。目前國內(nèi)Java之所以火爆,很大部分原因就是Java的跨平臺特性。雖然后來微軟的C#也追隨了Java的腳步,但由于更新太慢,幾乎都要被人遺忘了。至于C語言,C++,由于太古老,它們誕生的時候還沒有操作系統(tǒng)呢,所以基本指望不上跨平臺了。
跨平臺語言運行原理
編譯型語言
事實上,關(guān)于跨平臺,編譯型語言和解釋型語言走上了不同的道路。雖然道路不同,但原理是一樣的。
比如Java這門語言,之所以能夠跨平臺,是因為它在操作系統(tǒng)上層,又搭建了一個叫做Java虛擬機(Java Virtual Machine,簡稱 JVM)的東西。你可以把JVM理解成一個底層軟件,而且針對不同的平臺有不同的版本:Windows版,Linux版、MacOS版,這三個版本的JVM安裝在了這三個平臺上,我們編寫的Java源代碼會被JVM轉(zhuǎn)換成字節(jié)碼,字節(jié)碼是可以在Java虛擬機上運行的。流程如下圖:

這樣一來,你只需要寫一份源代碼就可以了,只要在操作系統(tǒng)中安裝上對應(yīng)的Java虛擬機,就可以平滑運行Java軟件了。所以Java打出的口號就是:一次編譯,處處運行。

解釋型語言
相對于編譯型這種只有少數(shù)語言支持跨平臺的語言來說,解釋型語言幾乎都能跨平臺?!耙淮尉帉?,處處運行”就是解釋型語言的特點。
那么為什么解釋型語言就能跨平臺呢?
這一切其實都歸功于解釋器。
解釋器其實就類似于Java虛擬機,也是編程語言與操作系統(tǒng)之間的中間層。官方會針對不同的平臺開發(fā)不同的解釋器,這些解釋器會把同樣的源代碼在不同的操作平臺下轉(zhuǎn)換成對應(yīng)平臺“認識”的機器碼,兼容了不同平臺之間的差異,從而解決了跨平臺的問題。
編譯型和解釋型語言另外一個明顯的區(qū)別就是:
使用編譯型語言開發(fā)的可執(zhí)行程序,源代碼是無法獲取的,所以程序一般是閉源的。
而解釋型語言由于一邊轉(zhuǎn)換一邊執(zhí)行的特性,軟件下載下來的都是源代碼,否則就無法運行,所以解釋型語言的程序一般是開源的。

關(guān)于Python
Python屬于解釋型語言,所以運行Python程序需要安裝對應(yīng)平臺的解釋器。也就是說我們使用Python無需考慮不同平臺的兼容性問題,目前常見的如Linux、Windows、MacOS、Android、PocketPC等操作系統(tǒng),Python都可以完美運行!
總結(jié)
我們將編譯型語言和解釋型語言的差異總結(jié)如下:
| 類型 | 原理 | 優(yōu)點 | 缺點 |
|---|---|---|---|
| 編譯型語言 | 通過編譯器將源代碼轉(zhuǎn)換為操作系統(tǒng)平臺對應(yīng)的機器碼 | 編譯一次,脫離編譯器也能運行,效率高 | 可移植性差,不夠靈活 |
| 解釋型語言 | 通過解釋器將源代碼轉(zhuǎn)換為操作系統(tǒng)平臺對應(yīng)的機器碼 | 跨平臺性好。 | 邊轉(zhuǎn)換機器碼邊執(zhí)行,效率較低 |