编译与解释语言

我试图更好地理解这种差异。 我在网上find了很多解释,但是它们倾向于抽象的差异,而不是实际的含义。

我的大部分编程经验都是使用CPython(dynamic的,解释的)和Java(静态的,编译的)。 但是,我知道还有其他种类的解释和编译语言。 除了可执行文件可以从以编译语言编写的程序分发的事实之外,每种types都有什么优点/缺点? 我经常听到有人认为解释型语言可以交互使用,但是我相信编译型语言也可以有交互式的实现,对吗?

编译后的语言是程序编译完成后,在目标机器的指令中expression的语言。 例如,在源代码中增加一个“+”操作可以直接翻译成机器代码中的“ADD”指令。

解释型语言是指目标机器不直接执行指令,而是由其他程序(通常使用本机语言编写)读取和执行的语言。 例如,解释器在运行时可以识别相同的“+”操作,然后用适当的参数调用自己的“add(a,b)”函数,然后执行机器码“ADD”指令。

你可以用编译语言做解释语言中的任何事情,反之亦然 – 它们都是图灵完备的。 但两者在实施和使用上都有优点和缺点。

我将完全概括(纯粹主义者原谅我!),但是,粗略地说,这里是编译语言的优点:

  • 通过直接使用目标机器的本地代码来提高性能
  • 在编译阶段有机会应用相当强大的优化

这里是解释型语言的优点:

  • 更容易实现(编写好的编译器非常困难!!)
  • 无需运行编译阶段:可以直接“即时”执行代码
  • dynamic语言可以更方便

请注意,像字节码编译这样的现代技术增加了一些额外的复杂性 – 这里发生的是,编译器针对的是与底层硬件不同的“虚拟机”。 然后可以在稍后阶段再次编译这些虚拟机指令以得到本地代码(例如,由Java JVM JIT编译器完成)。

一种语言本身既不被编译也不被解释,只是一种语言的具体实现。 Java是一个很好的例子。 有一个基于字节码的平台(JVM),一个本地编译器(gcj)和一个Java超集(bsh)的插入程序。 那么Java现在是什么? 字节码编译,本地编译或解释?

其他编译和解释的语言是Scala,Haskell或Ocaml。 每种语言都有一个交互式解释器,以及一个编译器,用于字节码或本地机器码。

因此,通常用“编译”和“解释”对语言进行分类并不合理。

开始思考: 从过去的爆炸

曾几何时,很久以前,住在计算机翻译和编译器的地方。 随之而来的是各种各样的事情。 当时的一般意见是这样的:

  • 口译员:快速开发(编辑和运行)。 执行速度慢,因为每次执行语句时都必须将其解释为机器代码(想想循环执行的次数是多less)。
  • 编译器:开发速度慢(编辑,编译,链接和运行,编译/链接步骤可能需要很长的时间)。 快速执行。 整个程序已经在本机机器码中。

解释程序和编译程序之间存在一个或两个数量级的运行时间性能差异。 其他的区别点,例如代码的运行时可变性,也有一些兴趣,但主要的区别是围绕运行时性能问题。

今天的景观已经发展到这样的程度,编译/解释的区别几乎是无关紧要的。 许多编译语言调用不完全基于机器代码的运行时服务。 另外,大多数解释型语言在执行之前被“编译”成字节码。 从执行速度的angular度来看,字节码解释器可以非常有效,并且可以与一些编译器生成的代码相媲美。

经典的区别在于编译器生成本地机器代码,解释器使用某种运行时系统即时读取源代码和生成的机器代码。 今天几乎没有经典的解释器了,几乎所有的解释器都编译成字节码(或其他半编译状态),然后在虚拟的“机器”上运行。

极端和简单的情况:

  • 编译器将以目标机器的本机可执行格式生成二进制可执行文件。 该二进制文件包含除系统库以外的所有必需资源; 它已经准备好运行,没有进一步的准备和处理,并且像闪电一样运行,因为代码是目标机器上CPU的本地代码。

  • 口译人员会在循环中向用户显示一个提示,在那里他可以input语句或代码,当碰到RUN或相当的时候,解释器将检查,扫描,parsing和解释执行每一行,直到程序运行到停止点或错误。 由于每一行都是独立处理的,而解释者并没有从之前看过的行中“学习”任何东西,所以每一行都会产生将人类可读的语言转换为机器指令的努力,所以它的速度很慢。 好的一面是,用户可以通过各种方式检查和交互程序:更改variables,更改代码,在跟踪或debugging模式下运行…无论如何。

让我解释一下,生活不再那么简单了。 例如,

  • 许多口译员会预先编译他们给出的代码,因此翻译步骤不必一再重复。
  • 一些编译器不会编译CPU特定的机器指令,而是编译字节码,这是一种虚构机器的人造机器代码。 这使编译后的程序更加便于携带,但是在每个目标系统上都需要一个字节码解释器。
  • 字节码解释器(我在这里看Java)倾向于在执行之前重新编译它们为目标部分的CPU获取的字节码(称为JIT)。 为了节省时间,通常只对经常运行的代码(热点)进行。
  • 一些像解释器一样外观和行为的系统(比如Clojure)立即编译他们得到的任何代码,但允许交互式访问程序的环境。 这基本上是解释器与二进制编译速度的便利。
  • 一些编译器并不真正编译,他们只是预先消化和压缩代码。 我后来听说Perl是如何工作的。 所以有时编译器只是做了一些工作,大部分仍然是解释。

最后,最近,解释与编译是一个折中的方法,花费在编译上的时间往往是由更好的运行时性能来获得回报,而解释性环境给了更多的交互机会。 编译与解释主要是关于“理解”程序的工作如何在不同的过程之间划分的问题,而现在的语言和产品试图提供两全其美的解决scheme。

http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages

没有什么区别,因为“编译的编程语言”和“解释的编程语言”不是有意义的概念。 任何编程语言,我的意思是任何,都可以被解释或编译。 因此,解释和编译是实现技术,而不是语言的属性。

解释是一种技术,即另一个程序,即解释者,代表被解释的程序执行操作,以便运行它。 如果你可以想象一下,阅读一个程序,按照所说的一步一步做,就可以在一张草稿纸上说,这正是解释者所做的。 解释一个程序的一个常见原因是解释者相对容易编写。 另一个原因是,口译员可以监视程序在运行时试图执行的操作,从而执行一个策略,例如为了安全。

编译是一种用一种语言(“源语言”)编写的程序被翻译成另一种语言的程序(“目标语言”)的技术,希望其意味着与原始程序相同的东西。 在进行翻译时,编译器通常还会尝试以使目标程序更快(而不改变其含义)的方式来转换程序。 编译一个程序的一个常见原因是有很好的方法来快速运行对象语言的程序,而且不需要沿途解释源语言的开销。

基于上述定义,您可能已经猜到,这两种实现技术并不相互排斥,甚至可能是互补的。 传统上,编译器的对象语言是机器代码或类似的东西,它是指特定计算机CPU所理解的任何编程语言。 然后机器代码就会在“金属上”运行(尽pipe人们可能会看到,如果看上去足够紧密,“金属”的作用就像解释器一样)。 然而今天,使用编译器来生成目标代码是很常见的,例如,这就是Java用来(有时还是)的工作原理。 有些编译器会将其他语言翻译成JavaScript,然后经常在Web浏览器中运行,这可能会解释JavaScript,或将其编译为虚拟机或本机代码。 我们也有机器代码的解释器,可以用来模拟另一种硬件。 或者,可以使用一个编译器来生成目标代码,这个目标代码就是另一个编译器的源代码,甚至可以在内存中编译代码,然后运行。 。 。 你明白了。 有很多方法可以将这些概念结合起来。

解释源代码比编译源代码最大的优点是便携性

如果您的源代码已编译完成,则需要针对希望程序运行的每种types的处理器和/或平台编译不同的可执行文件(例如,一个用于Windows x86,一个用于Windows x64,另一个用于Linux x64等上)。 此外,除非您的代码完全符合标准,并且不使用任何平台特定的函数/库,否则实际上您将需要编写和维护多个代码库!

如果你的源代码被解释了,你只需要写一次它就可以在任何平台上被一个合适的解释器解释和执行! 它是便携式的 ! 请注意,解释器本身是为特定平台编写和编译的可执行程序。

编译代码的一个优点是它隐藏了来自最终用户的源代码 (可能是知识产权 ),因为不是部署原始的人类可读源代码,而是部署一个难以理解的二进制可执行文件。

首先澄清一下,Java并没有完全静态编译,而是以C ++的方式进行链接。 它被编译成字节码,然后由JVM解释。 JVM可以直接编译本机机器语言,但不一定要这样做。

更重要的一点是:我认为交互性是主要的实际区别。 因为所有的东西都被解释了,所以你可以拿一小段代码,parsing并运行它,以抵御当前的环境状态。 因此,如果你已经执行了初始化一个variables的代码,那么你就可以访问这个variables,等等。它真的适合于像函数式样的东西。

然而,解释花费了很多,特别是当你有一个大量的参考和上下文的系统。 根据定义,这是浪费的,因为相同的代码可能需要两次解释和优化(尽pipe大多数运行时都有一些caching和优化)。 尽pipe如此,您还是需要一个运行时成本,而且通常需要一个运行时环境 您也不太可能看到复杂的过程间优化,因为目前它们的性能不够充分。

因此,对于不会有太大变化的大型系统,对于某些语言,预先编译和预先链接所有内容更有意义,可以做所有优化。 这最终是针对目标机器已经优化的非常精简的运行时间。

至于产生的执行,这与它没有什么关系,恕我直言。 您通常可以从编译语言创build可执行文件。 但是你也可以使用解释型语言创build一个可执行文件,只不过解释器和运行时已经打包在可执行文件中了,而且是隐藏的。 这意味着您通常仍然支付运行时成本(尽pipe我确信对于某些语言,可以将所有内容都转换为可执行文件)。

我不同意所有的语言都可以互动。 某些语言,比如C,与机器和整个链接结构紧密相连,我不确定你可以构build一个有意义的,完整的交互式版本

编译器和解释器完成相同的工作:将编程语言翻译成另一种通常靠近硬件的通用语言(通常是直接可执行的机器代码)。

传统上,“编译”意味着翻译一次完成,由开发人员完成,并将生成的可执行文件分发给用户。 纯粹的例子:C ++。 编译通常需要很长时间,并尝试执行大量昂贵的优化,以便生成的可执行文件运行得更快。 最终用户没有自己编译东西的工具和知识,而且可执行文件通常需要在各种硬件上运行,所以不能进行许多硬件特定的优化。 在开发过程中,单独的编译步骤意味着更长的反馈周期。

传统上,“解释”意味着当用户想要运行该程序时,翻译发生在“飞行中”。 纯粹的例子:香草PHP。 一个天真的解释器每次运行时都必须parsing和翻译每一段代码,这使得它非常缓慢。 它不能做复杂的,昂贵的优化,因为它们比在执行中保存的时间要花费更多的时间。 但是它可以充分利用运行的硬件的function。 缺乏单独的编译步骤会缩短开发过程中的反馈时间。

但是现在的“编译与解释”不是一个黑白的问题,而是两者之间的阴影。 朴素的,简单的口译员已经绝迹了。 许多语言使用两步过程,其中高级代码被转换为独立于平台的字节码(解释更快)。 然后你就有了“即时编译器”,每次程序运行时最多编译一次代码,有时会caching结果,甚至智能地决定解释很less运行的代码,并为运行很多的代码做强大的优化。 在开发过程中,即使是传统的编译语言,debugging器也能够在正在运行的程序中切换代码。

要给出实际的答案是相当困难的,因为不同之处在于语言定义本身。 可以为每一种编译语言构build一个解释器,但不可能为每种解释语言构build一个编译器。 这非常关乎一种语言的正式定义。 所以理论信息学的东西noboby喜欢大学。

Python Book 2015©2015 Imagine Publishing Ltd版权所有,仅仅是通过第10页中提到的以下提示来缩小差异:

像Python这样的解释性语言就是将源代码转换为机器代码,然后在程序运行时执行的语言。 这与C编译的语言不同,在C语言中,源代码只被转换为机器代码 – 每次运行程序时,都会执行生成的机器代码。

编译是使用编译的编程语言编写的代码创build可执行程序的过程。 编译允许计算机运行并理解该程序,而不需要用于创build它的编程软件。 在编译程序时,通常会针对与IBM兼容的计算机配合使用的特定平台(例如IBM平台)编译,而不是其他平台(例如Apple平台)。 第一个编译器是由Grace Hopper在Harvard Mark I计算机上开发的。 今天,大多数高级语言将包括他们自己的编译器或者有可用于编译程序的工具包。 用于Java的编译器的一个很好的例子是Eclipse,与C和C ++一起使用的编译器的例子是gcc命令。 根据程序的大小,应该花几秒钟或几分钟的时间来编译,如果在编译时没有遇到错误,则创build一个可执行文件。检查这些信息