1. 程式人生 > 其它 >編譯型語言和解釋型語言的區別

編譯型語言和解釋型語言的區別

編譯型和解釋型

摘自語言中文網-phthon-phthon程式設計基礎

我們編寫的原始碼是人類語言,我們自己能夠輕鬆理解;但是對於計算機硬體(CPU),原始碼就是天書,根本無法執行,計算機只能識別某些特定的二進位制指令,在程式真正執行之前必須將原始碼轉換成二進位制指令。

所謂的二進位制指令,也就是機器碼,是 CPU 能夠識別的硬體層面的“程式碼”,簡陋的硬體(比如古老的微控制器)只能使用幾十個指令,強大的硬體(PC 和智慧手機)能使用成百上千個指令。

然而,究竟在什麼時候將原始碼轉換成二進位制指令呢?不同的程式語言有不同的規定:

  • 有的程式語言要求必須提前將所有原始碼一次性轉換成二進位制指令,也就是生成一個可執行程式(Windows 下的 .exe),比如C語言、

    C++、Golang、Pascal(Delphi)、彙編等,這種程式語言稱為編譯型語言,使用的轉換工具稱為編譯器。

  • 有的程式語言可以一邊執行一邊轉換,需要哪些原始碼就轉換哪些原始碼,不會生成可執行程式,比如 PythonJavaScriptPHP、Shell、MATLAB 等,這種程式語言稱為解釋型語言,使用的轉換工具稱為直譯器。

簡單理解,編譯器就是一個“翻譯工具”,類似於將中文翻譯成英文、將英文翻譯成俄文。但是,翻譯原始碼是一個複雜的過程,大致包括詞法分析、語法分析、語義分析、效能優化、生成可執行檔案等五個步驟,期間涉及到複雜的演算法和硬體架構。直譯器與此類似,有興趣的讀者請參考《編譯原理》一書,本文不再贅述。

JavaC# 是一種比較奇葩的存在,它們是半編譯半解釋型的語言,原始碼需要先轉換成一種中間檔案(位元組碼檔案),然後再將中間檔案拿到虛擬機器中執行。Java 引領了這種風潮,它的初衷是在跨平臺的同時兼顧執行效率;C# 是後來的跟隨者,但是 C# 一直止步於 Windows 平臺,在其它平臺鮮有作為。

那麼,編譯型語言和解釋型語言各有什麼特點呢?它們之間有什麼區別?

編譯型語言

對於編譯型語言,開發完成以後需要將所有的原始碼都轉換成可執行程式,比如 Windows 下的.exe檔案,可執行程式裡面包含的就是機器碼。只要我們擁有可執行程式,就可以隨時執行,不用再重新編譯了,也就是“一次編譯,無限次執行”。

在執行的時候,我們只需要編譯生成的可執行程式,不再需要原始碼和編譯器了,所以說編譯型語言可以脫離開發環境執行。

編譯型語言一般是不能跨平臺的,也就是不能在不同的作業系統之間隨意切換。

編譯型語言不能跨平臺表現在兩個方面:

1) 可執行程式不能跨平臺

可執行程式不能跨平臺很容易理解,因為不同作業系統對可執行檔案的內部結構有著截然不同的要求,彼此之間也不能相容。不能跨平臺是天經地義,能跨平臺反而才是奇葩。

比如,不能將 Windows 下的可執行程式拿到 Linux 下使用,也不能將 Linux 下的可執行程式拿到 Mac OS 下使用(雖然它們都是類 Unix 系統)。

另外,相同作業系統的不同版本之間也不一定相容,比如不能將 x64 程式(Windows 64 位程式)拿到 x86 平臺(Windows 32 位平臺)下執行。但是反之一般可行,因為 64 位 Windows 對 32 位程式作了很好的相容性處理。

2) 原始碼不能跨平臺

不同平臺支援的函式、型別、變數等都可能不同,基於某個平臺編寫的原始碼一般不能拿到另一個平臺下編譯。我們以C語言為例來說明。

【例項1】在C語言中要想讓程式暫停可以使用“睡眠”函式,在 Windows 平臺下該函式是 Sleep(),在 Linux 平臺下該函式是 sleep(),首字母大小寫不同。其次,Sleep() 的引數是毫秒,sleep() 的引數是秒,單位也不一樣。

以上兩個原因導致使用暫停功能的C語言程式不能跨平臺,除非在程式碼層面做出相容性處理,非常麻煩。

【例項2】雖然不同平臺的C語言都支援 long 型別,但是不同平臺的 long 的長度卻不同,例如,Windows 64 位平臺下的 long 佔用 4 個位元組,Linux 64 位平臺下的 long 佔用 8 個位元組。

我們在 Linux 64 位平臺下編寫程式碼時,將 0x2f1e4ad23 賦值給 long 型別的變數是完全沒有問題的,但是這樣的賦值在 Windows 平臺下就會導致數值溢位,讓程式產生錯誤的執行結果。

讓人苦惱的,這樣的錯誤一般不容易察覺,因為編譯器不會報錯,我們也記不住不同型別的取值範圍。

解釋型語言

對於解釋型語言,每次執行程式都需要一邊轉換一邊執行,用到哪些原始碼就將哪些原始碼轉換成機器碼,用不到的不進行任何處理。每次執行程式時可能使用不同的功能,這個時候需要轉換的原始碼也不一樣。

因為每次執行程式都需要重新轉換原始碼,所以解釋型語言的執行效率天生就低於編譯型語言,甚至存在數量級的差距。計算機的一些底層功能,或者關鍵演算法,一般都使用 C/C++ 實現,只有在應用層面(比如網站開發、批處理、小工具等)才會使用解釋型語言。

在執行解釋型語言的時候,我們始終都需要原始碼和直譯器,所以說它無法脫離開發環境。

當我們說“下載一個程式(軟體)”時,不同型別的語言有不同的含義:

  • 對於編譯型語言,我們下載到的是可執行檔案,原始碼被作者保留,所以編譯型語言的程式一般是閉源的。

  • 對於解釋型語言,我們下載到的是所有的原始碼,因為作者不給原始碼就沒法執行,所以解釋型語言的程式一般是開源的。

相比於編譯型語言,解釋型語言幾乎都能跨平臺,“一次編寫,到處執行”是真是存在的,而且比比皆是。那麼,為什麼解釋型語言就能快平臺呢?

這一切都要歸功於直譯器!

我們所說的跨平臺,是指原始碼跨平臺,而不是直譯器跨平臺。直譯器用來將原始碼轉換成機器碼,它就是一個可執行程式,是絕對不能跨平臺的。

官方需要針對不同的平臺開發不同的直譯器,這些直譯器必須要能夠遵守同樣的語法,識別同樣的函式,完成同樣的功能,只有這樣,同樣的程式碼在不同平臺的執行結果才是相同的。

你看,解釋型語言之所以能夠跨平臺,是因為有了直譯器這個中間層。在不同的平臺下,直譯器會將相同的原始碼轉換成不同的機器碼,直譯器幫助我們遮蔽了不同平臺之間的差異。

關於 Python

Python 屬於典型的解釋型語言,所以執行 Python 程式需要直譯器的支援,只要你在不同的平臺安裝了不同的直譯器,你的程式碼就可以隨時執行,不用擔心任何相容性問題,真正的“一次編寫,到處執行”。

Python 幾乎支援所有常見的平臺,比如 Linux、Windows、Mac OS、Android、FreeBSD、Solaris、PocketPC 等,你所寫的 Python 程式碼無需修改就能在這些平臺上正確執行。也就是說,Python 的可移植性是很強的。

總結

我們將編譯型語言和解釋型語言的差異總結為下表:

型別原理優點缺點
編譯型語言 通過專門的編譯器,將所有原始碼一次性轉換成特定平臺(Windows、Linux 等)執行的機器碼(以可執行檔案的形式存在)。 編譯一次後,脫離了編譯器也可以執行,並且執行效率高。 可移植性差,不夠靈活。
解釋型語言 由專門的直譯器,根據需要將部分原始碼臨時轉換成特定平臺的機器碼。 跨平臺性好,通過不同的直譯器,將相同的原始碼解釋成不同平臺下的機器碼。 一邊執行一邊轉換,效率很低。