你知道「編譯」與「解釋」的區(qū)別嗎到逊?
最近在看一些編譯過程的知識點,看的比較多的是英文文獻(xiàn)滤钱。
在這之間經(jīng)常遇到的兩個單詞讓我著實迷惑:Compiler, Interpreter
中文翻譯分別是:編譯器觉壶,解釋器。
如果有人問我們「你知道什么是編譯器么件缸?」铜靶,
我們很有可能首先蔑視一下這個人,然后說:「知道啊他炊,不就編譯編程語言的程序嘛争剿!」
要是別人再追問一句「那你知道解釋器么?」痊末,
這時候很有可能也會說「知道啊蚕苇。」舌胶,心里開始沒什么底氣了捆蜀。
要是再問一句「那么編譯器和解釋器的區(qū)別是什么啊幔嫂?」,這是就開始瞎掰了
那么到底什么是「編譯器」誊薄,什么是「解釋器」履恩?
雖然對于兩個詞,我們很「耳熟」呢蔫,但是「能詳」么切心?
似乎我們并沒有認(rèn)真對待這兩個詞匯飒筑。
什么是編譯器
摘自 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.
大概意思:
編譯器是一種計算機(jī)程序,負(fù)責(zé)把一種編程語言編寫的源碼轉(zhuǎn)換成另外一種計算機(jī)代碼胆萧,后者往往是以二進(jìn)制的形式被稱為目標(biāo)代碼(object code)鸳玩。這個轉(zhuǎn)換的過程通常的目的是生成可執(zhí)行的程序赊抖。
編譯器的產(chǎn)出是「另外一種代碼」,然后這些代碼等著被別人拿來執(zhí)行肤晓,如果還不能直接被執(zhí)行,那么還需要再編譯或解釋一遍认然,再交由計算機(jī)硬件執(zhí)行补憾。
編譯器,往往是在「執(zhí)行」之前完成卷员,產(chǎn)出是一種可執(zhí)行或需要再編譯或者解釋的「代碼」盈匾。
什么是解釋器
摘自 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.
大概意思:
在計算機(jī)科學(xué)中,解釋器是一種計算機(jī)程序毕骡,它直接執(zhí)行由編程語言或腳本語言編寫的代碼削饵,并不會把源代碼預(yù)編譯成機(jī)器碼。一個解釋器未巫,通常會用以下的姿勢來執(zhí)行程序代碼:
分析源代碼窿撬,并且直接執(zhí)行。
把源代碼翻譯成相對更加高效率的中間碼橱赠,然后立即執(zhí)行它尤仍。
執(zhí)行由解釋器內(nèi)部的編譯器預(yù)編譯后保存的代碼
可以把解釋器看成一個黑盒子,我們輸入源碼狭姨,它就會實時返回結(jié)果宰啦。
不同類型的解釋器,黑盒子里面的構(gòu)造不一樣饼拍,有些還會集成編譯器赡模,緩存編譯結(jié)果,用來提高執(zhí)行效率(例如 Chrome V8 也是這么做的)师抄。
解釋器通常是工作在「運(yùn)行時」漓柑,并且對于我們輸入的源碼,是一行一行的解釋然后執(zhí)行叨吮,然后返回結(jié)果辆布。
分兩個維度比較一下
表現(xiàn) Behavior
編譯器把源代碼轉(zhuǎn)換成其他的更低級的代碼(例如二進(jìn)制碼、機(jī)器碼)茶鉴,但是不會執(zhí)行它锋玲。
解釋器會讀取源代碼,并且直接生成指令讓計算機(jī)硬件執(zhí)行涵叮,不會輸出另外一種代碼惭蹂。
性能 Performance
編譯器會事先用比較多的時間把整個程序的源代碼編譯成另外一種代碼伞插,后者往往較前者更加接近機(jī)器碼,所以執(zhí)行的效率會更加高盾碗。時間是消耗在預(yù)編譯的過程中媚污。
解釋器會一行一行的讀取源代碼,解釋廷雅,然后立即執(zhí)行耗美。這中間往往使用相對簡單的詞法分析、語法分析榜轿,壓縮解釋的時間幽歼,最后生成機(jī)器碼,交由硬件執(zhí)行谬盐。解釋器適合比較低級的語言甸私。但是相對于預(yù)編譯好的代碼,效率往往會更低飞傀。如何減少解釋的次數(shù)和復(fù)雜性皇型,是提高解釋器效率的難題。
關(guān)于代碼砸烦,需要知道的幾個概念
在看了不少不多關(guān)于「編譯和解釋」的文章之后弃鸦,我發(fā)現(xiàn)下面的詞匯是大量出現(xiàn)的。
知道這些詞匯代表的意思幢痘,以及對應(yīng)的層次唬格,能夠更好地看懂別人所要表達(dá)的意思。
高級語言代碼 High-Level Code
高級語言代碼颜说,自然是指由高級編程語言編寫代碼购岗,對計算機(jī)的細(xì)節(jié)有更高層次的抽象。
相對于低級編程語言(low-level programming language)更接近自然語言(人類的語言)门粪。
集成一系列的自動工具(垃圾回收喊积,內(nèi)存管理等),會讓程序員延長壽命玄妈,更快樂的編寫出更簡潔乾吻,更易讀的程序代碼。
低級語言代碼 Low-Level Code
低級語言代碼拟蜻,指由低級編程語言編寫的代碼绎签,相對高級語言,少了更多的抽象概念酝锅,更加接近于匯編或者機(jī)器指令辜御。
但是這也意味著代碼的可移植性很差。
在我看來屈张,高與低擒权,只是一組相對詞而已。
越高級的語言阁谆,性能碳抄、自由度越不及低級語言。
但是在抽象场绿、可讀可寫性剖效、可移植性越比低級語言優(yōu)秀。
在以前的年代焰盗,C/C++語言相對匯編語言璧尸,機(jī)器指令來說,肯定是高級語言熬拒。
而到了今天爷光,我們更多人對C語言偏向認(rèn)知為「低級語言」。
或許未來世界的開發(fā)者澎粟,看我們現(xiàn)在所熟悉的Java蛀序、PHP、Python活烙、ECMAScript等等徐裸,都是「low」到爆的語言。
匯編語言 Assembly Language
匯編語言作為一門低級語言啸盏,對應(yīng)于計算機(jī)或者其他可編程的硬件重贺。
它和計算機(jī)的體系結(jié)構(gòu)以及機(jī)器指令是強(qiáng)關(guān)聯(lián)的。
換句話說回懦,就是不同的匯編語言代碼對應(yīng)特定的硬件气笙,所以不用談可移植性了。
相對于需要編譯和解釋的高級語言代碼來說粉怕,匯編代碼只需要翻譯成機(jī)器碼就可以執(zhí)行了健民。
所以匯編語言也往往被稱作象征性機(jī)器碼(symbolic machine code)
字節(jié)碼 Byte Code
字節(jié)碼嚴(yán)格來說不算是編程語言,而是高級編程語言為了種種需求(可移植性贫贝、可傳輸性秉犹、預(yù)編譯等)而產(chǎn)生的中間碼(Intermediate Code)。
它是由一堆指令集組成的代碼稚晚,例如在javac編譯過后的java源碼產(chǎn)生的就是字節(jié)碼崇堵。
源碼在編譯的過程中,是需要進(jìn)行「詞法分析 → 語法分析 → 生成目標(biāo)代碼」等過程的客燕,在預(yù)編譯的過程中鸳劳,就完成這部分工作,生成字節(jié)碼也搓。
然后在后面交由解釋器(這里通常指編程語言的虛擬機(jī))解釋執(zhí)行赏廓,省去前面預(yù)編譯的開銷涵紊。
機(jī)器碼 Machine Code
機(jī)器碼是一組可以直接被CPU執(zhí)行的指令集,
每一條指令都代表一個特定的任務(wù)幔摸,或者是加載摸柄,或者是跳轉(zhuǎn),亦或是計算操作等等既忆。
所有可以直接被CPU執(zhí)行的程序驱负,都是由這么一系列的指令組成的。
機(jī)器碼可是看作是編譯過程中患雇,最低級的代碼跃脊,因外再往下就是交由硬件來執(zhí)行了。
當(dāng)然機(jī)器碼也是可以被編輯的苛吱,但是以人類難以看懂的姿勢存在酪术,可讀性非常差。
從熟悉的編程語言的角度來看看
從左往右看又谋,
以 Java 為例拼缝,我們在文本編譯器寫好了 Java 代碼,交由「編譯器」編譯成 Java Bytecode彰亥。然后 Bytecode 交由 JVM 來執(zhí)行咧七,這時候 JVM 充當(dāng)了「解釋器」的角色,在解釋 Bytecode 成 Machine Code 的同時執(zhí)行它任斋,返回結(jié)果继阻。
以 BASIC 語言(早期的可以由計算機(jī)直譯的語言) 為例,通過文本編譯器編寫好废酷,不用經(jīng)歷「編譯」的過程瘟檩,就可以直接交由操作系統(tǒng)內(nèi)部來進(jìn)行「解釋」然后執(zhí)行。
以 C 語言為例澈蟆,我們在文本編譯器編寫好源代碼墨辛,然后運(yùn)行 gcc hello.c 編譯出 hello.out 文件,該文件由一系列的機(jī)器指令組成的機(jī)器碼趴俘,可以直接交由硬件來執(zhí)行睹簇。
抽象看本質(zhì):人與計算機(jī)之間的鴻溝
無論是最近在看《暗時間》的作者劉未鵬,還是前一段時間聽《以產(chǎn)品思維寫文章》講座的阿禪寥闪,還是其他的很多聰明的人太惠。
他們都強(qiáng)調(diào)「抽象看本質(zhì)」的能力,能從事物本身抽象出共通屬性疲憋,看待本質(zhì)凿渊。
這也是很多人所說的「跳出這個框框再看」的思維方式。
無論是「編譯 Compile」還是「解釋 Interpret」。
本質(zhì)還是「人與計算機(jī)的交流形式」埃脏,人的語言最終轉(zhuǎn)換成機(jī)器語言搪锣。
一句 「Hello World」,經(jīng)過一些列的「編譯」和「解釋」剂癌,最終轉(zhuǎn)換成一系列包含機(jī)器指令的那些0和1淤翔,機(jī)器傻傻執(zhí)行完之后,告訴你結(jié)果佩谷。
就這么一個過程,我們就需要很多的翻譯官监嗜。
有些翻譯官可以做到同聲傳譯(解釋)谐檀,有些翻譯官卻只能把我們的意圖記下來再全部翻譯(編譯)給計算機(jī)。
而往往一個翻譯官能力有限裁奇,也只能把你的語言桐猬,翻譯成另外一種低級點的語言,再由另外懂這個語言的翻譯官來翻譯更接近計算機(jī)能讀得懂的語言刽肠。
一句話描述「編譯」與「解釋」溃肪?
不如這張圖來得直接:
[圖片上傳失敗...(image-677da4-1510394488709)]
一句話描述編譯與解釋
編譯 Compile:把整個程序源代碼翻譯成另外一種代碼,然后等待被執(zhí)行音五,發(fā)生在運(yùn)行之前惫撰,產(chǎn)物是「另一份代碼」。
解釋 Interpret:把程序源代碼一行一行的讀懂然后執(zhí)行躺涝,發(fā)生在運(yùn)行時厨钻,產(chǎn)物是「運(yùn)行結(jié)果」。
參考
http://stackoverflow.com/questions/2377273/how-does-an-interpreter-compiler-work
https://www.wikiwand.com/en/Interpreter_
https://www.wikiwand.com/en/Compiler
https://www.wikiwand.com/en/Machine_code
https://www.wikiwand.com/en/High-level_programming_language
https://www.wikiwand.com/en/Low-level_programming_language
https://www.wikiwand.com/en/Bytecode