我正在尝试更好地理解它们之间的区别。我在网上找到了很多解释,但是它们倾向于抽象的差异,而不是实际的含义。
我的大部分编程经验都来自CPython(动态的,解释的)和Java(静态的,编译的)。但是,我知道还有其他种类的解释和编译语言。除了可以从以编译语言编写的程序中分发可执行文件这一事实之外,每种类型是否都有优点/缺点?通常,我听到人们争辩说解释语言可以交互使用,但是我相信编译语言也可以具有交互实现,对吗?
我正在尝试更好地理解它们之间的区别。我在网上找到了很多解释,但是它们倾向于抽象的差异,而不是实际的含义。
我的大部分编程经验都来自CPython(动态的,解释的)和Java(静态的,编译的)。但是,我知道还有其他种类的解释和编译语言。除了可以从以编译语言编写的程序中分发可执行文件这一事实之外,每种类型是否都有优点/缺点?通常,我听到人们争辩说解释语言可以交互使用,但是我相信编译语言也可以具有交互实现,对吗?
Answers:
编译语言是一种程序,一旦编译,该程序就会在目标计算机的指令中表示出来。例如,源代码中的加号“ +”操作可以直接转换为机器代码中的“ ADD”指令。
一种解释语言是其中所述指令不被目标机器直接执行,而是读取和执行通过一些其它方案(其通常被写入本机机器的语言)。例如,解释器将在运行时识别相同的“ +”操作,然后使用适当的参数调用其自己的“ add(a,b)”函数,然后执行机器代码“ ADD”指令。
您可以使用解释语言或编译语言来做任何事情,反之亦然-它们都是图灵完整的。但是,两者在实现和使用上都有优点和缺点。
我将完全概括(纯粹主义者请原谅!),但是,粗略地讲,这是编译语言的优点:
以下是解释语言的优点:
请注意,诸如字节码编译之类的现代技术增加了一些额外的复杂性-此处发生的是,编译器针对的是“虚拟机”,该“虚拟机”与底层硬件不同。然后可以在以后的阶段再次编译这些虚拟机指令,以获取本机代码(例如,由Java JVM JIT编译器完成)。
语言本身既不会编译也不会解释,而仅是语言的特定实现。Java是一个完美的例子。有一个基于字节码的平台(JVM),一个本机编译器(gcj)和一个Java超集的插入器(bsh)。那么,Java现在是什么?字节码编译,本机编译还是解释?
Scala,Haskell或Ocaml是经过编译和解释的其他语言。这些语言中的每一种都有一个交互式解释器,以及用于字节码或本机代码的编译器。
因此,通常通过“编译”和“解释”对语言进行分类没有多大意义。
开始思考:过去的爆炸
很久很久以前,曾经有计算解释器和编译器。各种大惊小怪的结果使一个人的优胜劣汰。普遍的观点在当时是沿着线的东西:
在解释的程序和编译的程序之间存在一个或两个数量级的运行时性能差异。其他区别点,例如代码的运行时可变性,也引起了一些关注,但主要区别在于运行时性能问题。
如今,景观已发展到某种程度,以至于汇编/解释的区别几乎是无关紧要的。许多编译语言要求运行时服务不是完全基于机器代码的。而且,大多数解释语言在执行之前都会被“编译”为字节码。字节码解释器可能非常高效,并且从执行速度的角度来看,可以与某些编译器生成的代码相媲美。
经典的区别是,编译器使用某种运行时系统生成本机代码,解释器读取源代码并动态生成代码。如今,几乎没有经典的解释器了-几乎所有经典的解释器都编译成字节码(或其他半编译状态),然后在虚拟“机器”上运行。
极端简单的情况:
编译器将生成目标计算机的本机可执行文件格式的二进制可执行文件。该二进制文件包含除系统库以外的所有必需资源。它无需任何准备和处理即可运行,并且像闪电一样运行,因为该代码是目标计算机上CPU的本机代码。
解释器将在循环中向用户显示提示,用户可以在其中输入语句或代码,并且在命中RUN
或等效命令时,解释器将检查,扫描,解析并以解释方式执行每一行,直到程序运行至停止点或错误为止。因为每一行都是独立处理的,并且解释器不会从以前的行中“学到”任何东西,所以每行每次都需要将人类可读的语言转换为机器指令,所以这太慢了。从好的方面来说,用户可以通过各种方式检查程序并与之交互:更改变量,更改代码,在跟踪或调试模式下运行……等等。
顺便说一句,让我解释一下生活不再那么简单了。例如,
最终,如今,解释与编译是一个折衷方案,花费(一次)编译的时间通常会因更好的运行时性能而获得回报,但是解释性环境为交互提供了更多机会。编译与解释主要是关于如何“理解”程序的工作如何在不同的过程之间进行划分的问题,而如今,由于语言和产品试图同时兼顾两者的优势,这条线有些模糊。
来自http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages
这没有什么区别,因为“编译程序设计语言”和“解释程序设计语言”不是有意义的概念。任何编程语言(实际上是任何一种编程语言)都可以解释或编译。因此,解释和编译是实现技术,而不是语言的属性。
解释是一种技术,通过该技术,另一个程序(解释器)代表正在解释的程序执行操作以使其运行。如果您可以想象阅读程序并按照程序说的做一步一步,例如在草稿纸上说,那也是解释器的工作。解释程序的常见原因是解释器相对容易编写。另一个原因是,解释器可以监视程序在运行时试图执行的操作,以执行安全性策略。
编译是一种技术,通过该技术可以将用一种语言(“源语言”)编写的程序转换为另一种语言(“目标语言”)的程序,这希望与原始程序具有相同的含义。在进行翻译时,编译器通常还会尝试以使目标程序更快的方式(不改变其含义!)对程序进行转换。编译程序的一个常见原因是,有一种很好的方法可以以目标语言快速运行程序,而无需一路解释源语言。
根据上述定义,您可能已经猜到这两种实现技术不是互斥的,甚至可能是互补的。传统上,编译器的目标语言是机器代码或类似的东西,它表示特定计算机CPU可以理解的任何数量的编程语言。然后,机器代码将“运行在金属上”(尽管如果看起来足够接近,人们可能会发现“金属”的工作原理很像解释器)。但是,如今,使用编译器生成要解释的目标代码已经非常普遍了,例如,Java曾经(有时仍然这样做)就是这种方式。有些编译器会将其他语言翻译成JavaScript,然后通常在网络浏览器中运行,这些浏览器可能会解释JavaScript,或将其编译为虚拟机或本机代码。我们还提供了机器码解释器,可用于在另一种机器上模拟一种硬件。或者,可以使用编译器生成目标代码,然后该目标代码将成为另一编译器的源代码,后者甚至可以及时在内存中编译代码以使其运行,然后依次运行。。。你明白了。有很多方法可以组合这些概念。
与已编译的源代码相比,已解释的源代码的最大优势是PORTABILITY。
如果您的源代码已编译,则需要为要在其上运行程序的每种类型的处理器和/或平台编译一个不同的可执行文件(例如,一个用于Windows x86,一个用于Windows x64,一个用于Linux x64,等等。上)。此外,除非您的代码完全符合标准并且不使用任何平台特定的功能/库,否则您实际上将需要编写和维护多个代码库!
如果您的源代码被解释,则只需编写一次即可,并且可以由任何平台上的适当解释器来解释和执行它!它是便携式的!需要注意的是一个解释器本身是一个可执行程序的编写和编译为特定平台。
编译后代码的一个优点是,它向最终用户隐藏了源代码(可能是知识产权),因为您部署了晦涩的二进制可执行文件,而不是部署原始的人类可读源代码。
编译器和解释器完成相同的工作:将编程语言翻译为另一种编程语言,通常更接近硬件,通常指导可执行的机器代码。
传统上,“编译”是指这种翻译一次完成,由开发人员完成,然后将生成的可执行文件分发给用户。纯粹的例子:C ++。编译通常花费很长时间,并尝试进行大量昂贵的优化,以使生成的可执行文件运行更快。最终用户没有工具和知识来自己编译东西,并且可执行文件通常必须在各种硬件上运行,因此您不能进行许多针对硬件的优化。在开发过程中,单独的编译步骤意味着更长的反馈周期。
传统上,“已解释”是指当用户要运行程序时,翻译是“即时”进行的。纯粹的例子:香草PHP。天真的解释器每次运行时都必须解析和翻译每段代码,这使其非常慢。它无法进行复杂,成本高昂的优化,因为它们所花费的时间比执行所节省的时间还要长。但是它可以充分利用其运行的硬件的功能。缺少单独的编译步骤可减少开发过程中的反馈时间。
但是如今,“编译与解释”已不是一个黑白问题,介于两者之间。天真的,简单的口译员已经绝迹了。许多语言使用两步过程,其中将高级代码转换为平台无关的字节码(解释起来更快)。然后,您将拥有“及时编译器”,每个程序运行一次最多编译一次代码,有时缓存结果,甚至可以明智地决定解释很少运行的代码,并对运行频繁的代码进行强大的优化。在开发过程中,调试器甚至可以针对传统编译语言在正在运行的程序中切换代码。
首先,澄清一下,Java不是完全以C ++的方式静态编译和链接的。它被编译成字节码,然后由JVM解释。JVM可以及时对本机语言进行编译,但不必这样做。
更重要的是:我认为互动是主要的实际差异。由于所有内容均已解释,因此您可以摘录一小段代码,然后针对环境的当前状态进行解析和运行。因此,如果您已经执行过初始化变量的代码,则可以访问该变量,等等。它确实可以将其自身用于诸如功能样式之类的事情。
但是,解释会花费很多,尤其是当您拥有一个具有大量引用和上下文的大型系统时。根据定义,这是浪费的,因为可能必须两次解释和优化相同的代码(尽管大多数运行时对此都有一些缓存和优化)。尽管如此,您仍然需要支付运行时成本,并且经常需要运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能还不够互动。
因此,对于那些变化不大的大型系统,对于某些语言而言,预编译和预链接所有内容更有意义,请执行您可以做的所有优化。最终将获得非常精益的运行时,该运行时已针对目标计算机进行了优化。
至于生成可执行文件,与恕我直言无关。您通常可以使用编译语言创建可执行文件。但是,您也可以使用解释语言创建可执行文件,只是解释器和运行时已打包在可执行文件中,并且对您隐藏了。这意味着您通常仍需支付运行时成本(尽管我确信对于某些语言,有一些方法可以将所有内容转换为树可执行文件)。
我不同意所有语言都可以互动。某些语言(例如C)与机器和整个链接结构紧密相关,因此我不确定您是否可以构建有意义的完整交互式版本
Python图书©2015 Imagine Publishing Ltd,仅通过第10页中提到的以下提示来区分差异:
一种解释性语言(例如Python)是一种将源代码转换为机器代码,然后在每次程序运行时执行的语言。这与诸如C之类的编译语言不同,后者仅将源代码转换为机器代码一次-每次程序运行时都会执行生成的机器代码。
简短(不精确)的定义:
编译语言:整个程序立即转换为机器代码,然后由CPU运行机器代码。
解释的语言:逐行读取程序,一旦读取一行,CPU就会执行该行的机器指令。
但是,实际上,如今只有很少的语言是纯编译的或纯解释的,通常是混合的。有关图片的详细说明,请参见以下线程:
或我后来的博客文章:
https://orangejuiceliberationfront.com/the-difference-between-compiler-and-interpreter/