我們編寫的源**是人類語言,我們自己能夠輕鬆理解;但是對於計算機硬體(cpu),源**就是天書,根本無法執行,計算機只能識別某些特定的二進位制指令,在程式真正執行之前必須將源**轉換成二進位制指令。
所謂的二進位制指令,也就是機器碼,是 cpu 能夠識別的硬體層面的「**」,簡陋的硬體(比如古老的微控制器)只能使用幾十個指令,強大的硬體(pc 和智慧型手機)能使用成百上千個指令。
然而,究竟在什麼時候將源**轉換成二進位制指令呢?不同的程式語言有不同的規定:
簡單理解,編譯器就是乙個「翻譯工具」,類似於將中文翻譯成英文、將英文翻譯成俄文。但是,翻譯源**是乙個複雜的過程,大致包括詞法分析、語法分析、語義分析、效能優化、生成可執行檔案等五個步驟,期間涉及到複雜的演算法和硬體架構。直譯器與此類似,有興趣的讀者請參考《編譯原理》一書,本文不再贅述。
j**a 和 c# 是一種比較奇葩的存在,它們是半編譯半解釋型的語言,源**需要先轉換成一種中間檔案(位元組碼檔案),然後再將中間檔案拿到虛擬機器中執行。j**a 引領了這種風潮,它的初衷是在跨平台的同時兼顧執行效率;c# 是後來的跟隨者,但是 c# 一直止步於 windows 平台,在其它平台鮮有作為。
圖 1 編譯型語言和解釋型語言的執行流程
那麼,編譯型語言和解釋型語言各有什麼特點呢?它們之間有什麼區別?
對於編譯型語言,開發完成以後需要將所有的源**都轉換成可執行程式,比如 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 平台下就會導致數值溢位,讓程式產生錯誤的執行結果。
讓人苦惱的,這樣的錯誤一般不容易察覺,因為編譯器不會報錯,我們也記不住不同型別的取值範圍。
相比於編譯型語言,解釋型語言幾乎都能跨平台,「一次編寫,到處執行」是真是存在的,而且比比皆是。那麼,為什麼解釋型語言就能快平台呢?
這一切都要歸功於直譯器!
我們所說的跨平台,是指源**跨平台,而不是直譯器跨平台。直譯器用來將源**轉換成機器碼,它就是乙個可執行程式,是絕對不能跨平台的。
官方需要針對不同的平台開發不同的直譯器,這些直譯器必須要能夠遵守同樣的語法,識別同樣的函式,完成同樣的功能,只有這樣,同樣的**在不同平台的執行結果才是相同的。
你看,解釋型語言之所以能夠跨平台,是因為有了直譯器這個中間層。在不同的平台下,直譯器會將相同的源**轉換成不同的機器碼,直譯器幫助我們遮蔽了不同平台之間的差異。
python 屬於典型的解釋型語言,所以執行 python 程式需要直譯器的支援,只要你在不同的平台安裝了不同的直譯器,你的**就可以隨時執行,不用擔心任何相容性問題,真正的「一次編寫,到處執行」。
python 幾乎支援所有常見的平台,比如 linux、windows、mac os、android、freebsd、solaris、pocketpc 等,你所寫的 python **無需修改就能在這些平台上正確執行。也就是說,python 的可移植性是很強的。
我們將編譯型語言和解釋型語言的差異總結為下表:
型別原理
優點缺點
編譯型語言
通過專門的編譯器,將所有源**一次性轉換成特定平台(windows、linux 等)執行的機器碼(以可執行檔案的形式存在)。
編譯一次後,脫離了編譯器也可以執行,並且執行效率高。
可移植性差,不夠靈活。
解釋型語言
由專門的直譯器,根據需要將部分源**臨時轉換成特定平台的機器碼。
跨平台性好,通過不同的直譯器,將相同的源**解釋成不同平台下的機器碼。
一邊執行一邊轉換,效率很低。
編譯型語言和解釋型語言
計算機只能識別二進位制編碼,所以任何語言在交由計算機執行時必須要先轉換為機器碼。也就是像print hello 必須要轉換為型別01010這樣的機器碼。根據轉換時機的不同,語言分成了兩大類 編譯型語言 例如c語言,會在 執行前將 編譯為機器碼,然後將機器碼交由計算機執行。就型別於 a 原始碼 編譯 ...
編譯型語言和解釋型語言
參考 c語言中文網 python程式設計基礎 對於編譯型語言,開發完成以後需要將所有的源 都轉換成可執行程式,比如 windows 下的.exe檔案,可執行程式裡面包含的就是機器碼。只要我們擁有可執行程式,就可以隨時執行,不用再重新編譯了,也就是 一次編譯,無限次執行 在執行的時候,我們只需要編譯生...
編譯型語言和解釋性語言
1.計算機不能識別高階語言,計算機能夠直接識別並執行的語言,從目前看來只有機器語言。我們寫的高階語言要先翻譯成低階語言,才能被計算機執行,翻譯的方式有兩種 編譯和解釋,二者的目的是相同的,但是翻譯的時間不同。2.解釋型語言 直到執行的時候才翻譯,並且每執行一次翻譯一次 而編譯型語言執行和翻譯是分開的...