什麼是編譯器
摘自 Wiki Compiler 一段
A compiler is a computer program (or a set of programs) that
transforms source code written in a programming language (the source
language) into another computer language (the target language), with
the latter often having a binary form known as object code. The most
common reason for converting source code is to create an executable
program.
大概意思:
編譯器是一種計算機程序,負責把一種編程語言編寫的源碼轉換成另外一種計算機代碼,後者往往是以二進制的形式被稱爲目標代碼(object code)。這個轉換的過程通常的目的是生成可執行的程序。
編譯器的產出是「另外一種代碼」,然後這些代碼等着被別人拿來執行,如果還不能直接被執行,那麼還需要再編譯或解釋一遍,再交由計算機硬件執行。
編譯器,往往是在「執行」之前完成,產出是一種可執行或需要再編譯或者解釋的「代碼」。
什麼是解釋器
摘自 Wiki Interpreter 一段
In computer science, an interpreter is a computer program that
directly executes, i.e. performs, instructions written in a
programming or scripting language, without previously compiling them
into a machine language program. An interpreter generally uses one of
the following strategies for program execution:parse the source code and perform its behavior directly. translate
source code into some efficient intermediate representation and
immediately execute this. explicitly execute stored precompiled code
made by a compiler which is part of the interpreter system.
大概意思:
在計算機科學中,解釋器是一種計算機程序,它直接執行由編程語言或腳本語言編寫的代碼,並不會把源代碼預編譯成機器碼。一個解釋器,通常會用以下的姿勢來執行程序代碼:
分析源代碼,並且直接執行。
把源代碼翻譯成相對更加高效率的中間碼,然後立即執行它。
執行由解釋器內部的編譯器預編譯後保存的代碼
可以把解釋器看成一個黑盒子,我們輸入源碼,它就會實時返回結果。
不同類型的解釋器,黑盒子裏面的構造不一樣,有些還會集成編譯器,緩存編譯結果,用來提高執行效率(例如 Chrome V8 也是這麼做的)。
解釋器通常是工作在「運行時」,並且對於我們輸入的源碼,是一行一行的解釋然後執行,然後返回結果。
分兩個維度比較一下
表現 Behavior
編譯器把源代碼轉換成其他的更低級的代碼(例如二進制碼、機器碼),但是不會執行它。
解釋器會讀取源代碼,並且直接生成指令讓計算機硬件執行,不會輸出另外一種代碼。
性能 Performance
編譯器會事先用比較多的時間把整個程序的源代碼編譯成另外一種代碼,後者往往較前者更加接近機器碼,所以執行的效率會更加高。時間是消耗在預編譯的過程中。
解釋器會一行一行的讀取源代碼,解釋,然後立即執行。這中間往往使用相對簡單的詞法分析、語法分析,壓縮解釋的時間,最後生成機器碼,交由硬件執行。解釋器適合比較低級的語言。但是相對於預編譯好的代碼,效率往往會更低。如何減少解釋的次數和複雜性,是提高解釋器效率的難題。
關於代碼,需要知道的幾個概念
高級語言代碼 High-Level Code
高級語言代碼,自然是指由高級編程語言編寫代碼,對計算機的細節有更高層次的抽象。
相對於低級編程語言(low-level programming language)更接近自然語言(人類的語言)。
集成一系列的自動工具(垃圾回收,內存管理等),會讓程序員延長壽命,更快樂的編寫出更簡潔,更易讀的程序代碼。
低級語言代碼 Low-Level Code
低級語言代碼,指由低級編程語言編寫的代碼,相對高級語言,少了更多的抽象概念,更加接近於彙編或者機器指令。
但是這也意味着代碼的可移植性很差。
在我看來,高與低,只是一組相對詞而已。
越高級的語言,性能、自由度越不及低級語言。
但是在抽象、可讀可寫性、可移植性越比低級語言優秀。
在以前的年代,C/C++語言相對彙編語言,機器指令來說,肯定是高級語言。
而到了今天,我們更多人對C語言偏向認知爲「低級語言」。
彙編語言 Assembly Language
彙編語言作爲一門低級語言,對應於計算機或者其他可編程的硬件。
它和計算機的體系結構以及機器指令是強關聯的。
換句話說,就是不同的彙編語言代碼對應特定的硬件,所以不用談可移植性了。
相對於需要編譯和解釋的高級語言代碼來說,彙編代碼只需要翻譯成機器碼就可以執行了。
所以彙編語言也往往被稱作象徵性機器碼(symbolic machine code)
字節碼 Byte Code
字節碼嚴格來說不算是編程語言,而是高級編程語言爲了種種需求(可移植性、可傳輸性、預編譯等)而產生的中間碼(Intermediate Code)。
它是由一堆指令集組成的代碼,例如在javac編譯過後的java源碼產生的就是字節碼。
源碼在編譯的過程中,是需要進行「詞法分析 → 語法分析 → 生成目標代碼」等過程的,在預編譯的過程中,就完成這部分工作,生成字節碼。
然後在後面交由解釋器(這裏通常指編程語言的虛擬機)解釋執行,省去前面預編譯的開銷。
機器碼 Machine Code
機器碼是一組可以直接被CPU執行的指令集,
每一條指令都代表一個特定的任務,或者是加載,或者是跳轉,亦或是計算操作等等。
所有可以直接被CPU執行的程序,都是由這麼一系列的指令組成的。
機器碼可是看作是編譯過程中,最低級的代碼,因外再往下就是交由硬件來執行了。
當然機器碼也是可以被編輯的,但是以人類難以看懂的姿勢存在,可讀性非常差。
從熟悉的編程語言的角度來看看
從左往右看,
以 Java 爲例,我們在文本編譯器寫好了 Java 代碼,交由「編譯器」編譯成 Java Bytecode。然後 Bytecode 交由 JVM 來執行,這時候 JVM 充當了「解釋器」的角色,在解釋 Bytecode 成 Machine Code 的同時執行它,返回結果。
以 BASIC 語言(早期的可以由計算機直譯的語言) 爲例,通過文本編譯器編寫好,不用經歷「編譯」的過程,就可以直接交由操作系統內部來進行「解釋」然後執行。
以 C 語言爲例,我們在文本編譯器編寫好源代碼,然後運行 gcc hello.c 編譯出 hello.out 文件,該文件由一系列的機器指令組成的機器碼,可以直接交由硬件來執行。
抽象看本質:人與計算機之間的鴻溝
無論是「編譯 Compile」還是「解釋 Interpret」。
本質還是「人與計算機的交流形式」,人的語言最終轉換成機器語言。
一句 「Hello World」,經過一些列的「編譯」和「解釋」,最終轉換成一系列包含機器指令的那些0和1,機器傻傻執行完之後,告訴你結果。
就這麼一個過程,我們就需要很多的翻譯官。
有些翻譯官可以做到同聲傳譯(解釋),有些翻譯官卻只能把我們的意圖記下來再全部翻譯(編譯)給計算機。
而往往一個翻譯官能力有限,也只能把你的語言,翻譯成另外一種低級點的語言,再由另外懂這個語言的翻譯官來翻譯更接近計算機能讀得懂的語言。
一句話描述「編譯」與「解釋」?
不如這張圖來得直接:
一句話描述編譯與解釋
編譯 Compile:把整個程序源代碼翻譯成另外一種代碼,然後等待被執行,發生在運行之前,產物是「另一份代碼」。
解釋 Interpret:把程序源代碼一行一行的讀懂然後執行,發生在運行時,產物是「運行結果」。
轉載:http://huang-jerryc.com/2016/11/20/do-you-konw-the-different-between-compiler-and-interpreter/