编译语言与口译语言

时间:2010-07-16 13:35:33

标签: java python compiler-construction programming-languages interpreter

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

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

13 个答案:

答案 0 :(得分:424)

编译语言是指程序在编译后在目标机器的指令中表达的语言。例如,源代码中的附加“+”操作可以直接转换为机器代码中的“ADD”指令。

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

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

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

  • 直接使用目标计算机的本机代码,性能更快
  • 在编译阶段应用强大优化的机会

以下是解释语言的优点:

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

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

答案 1 :(得分:94)

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

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

因此,通常按“编译”和“解释”对语言进行分类并没有多大意义。

答案 2 :(得分:50)

开始考虑:来自过去的爆炸

很久很久以前,曾经生活在计算领域 口译员和编译员。随之而来的是各种各样的大惊小怪 一个在另一个上面。当时的一般意见是:

  • 口译员:快速开发(编辑和运行)。执行起来很慢,因为每个语句都必须被解释 每次执行时的机器代码(想想这对循环执行数千次的意义)。
  • 编译器:开发缓慢(编辑,编译,链接和运行。编译/链接步骤可能需要很长时间)。快速 执行。整个程序已经使用本机代码。

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

今天,景观已经发展到如此程度,以至于编译/解释的区别是 几乎无关紧要。许多 编译语言调用非运行时服务 完全基于机器代码。此外,大多数解释语言被“编译”为字节码 在执行之前。字节码解释器可以非常高效并且可以与某些编译器生成相匹敌 从执行速度的角度来看代码。

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

答案 3 :(得分:24)

极端简单的案例:

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

  • 解释器会在循环中向用户显示一个提示,在该循环中他可以输入语句或代码,并且在点击RUN或等效时,解释器将检查,扫描,解析和解释性地执行每一行直到程序运行到停止点或错误。因为每一行都是自己处理的,并且解释器没有“学习”任何东西,因为之前已经看过该行,所以每次为每一行都会产生将人类可读语言转换为机器指令的努力,因此它的速度很慢。从好的方面来说,用户可以通过各种方式检查和以其他方式与他的程序交互:更改变量,更改代码,以跟踪或调试模式运行......无论如何。

有了这些,请让我解释生活不再那么简单。例如,

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

最后,现在,解释与编译是一种权衡,花费的时间(一次)编译通常会得到更好的运行时性能的奖励,但解释性环境会提供更多的交互机会。编译与解释主要是关于“理解”程序的工作如何在不同的过程之间划分的问题,而且这些日子的界限有点​​模糊,因为语言和产品试图提供两全其美的优势。

答案 4 :(得分:20)

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

  

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

     

解释是一种技术,通过另一个程序,   解释器,代表程序执行操作   解释为了运行它。如果你能想象读一个程序   并且按照一步一步的说法,按照它说的做一步一步做   纸,这就是翻译的作用。一个常见的原因   解释一个程序是解释器相对容易   写。另一个原因是翻译可以监控什么   程序尝试在运行时执行,以执行策略,比如说   安全

     

编译是一种用一种语言编写的程序   (“源语言”)被翻译成另一个程序   语言(“对象语言”),希望意味着同样的事情   作为原始程序。在进行翻译时,这很常见   编译器也尝试以这样的方式转换程序   使对象程序更快(不改变其含义!)。一个   编译程序的常见原因是有一些好的方法   以对象语言快速运行程序,无需开销   在此过程中解释源语言。

     

根据上述定义,您可能已经猜到了这两个   实现技术不是相互排斥的,甚至可能是   补充。传统上,编译器的目标语言是   机器代码或类似的东西,指任意数量的   特定计算机CPU理解的编程语言。该   然后机器代码将“在金属上”运行(尽管人们可能会看到,如果   一个看起来足够紧密,“金属”的工作方式很像   解释器)。然而,今天,使用编译器是很常见的   生成要解释的对象代码 - 例如,这   是Java过去(有时仍然如此)的工作方式。有   那些将其他语言翻译成JavaScript的编译器   通常在Web浏览器中运行,可能会解释JavaScript,或者   将其编译为虚拟机或本机代码。我们也有口译员   用于机器代码,可用于模拟一种硬件   另一个。或者,可以使用编译器生成对象代码   那么另一个编译器的源代码,甚至可能编译   代码在内存中及时运行,反过来。 。 。你得到   这个想法。有很多方法可以将这些概念结合起来。

答案 5 :(得分:11)

解释源代码优于已编译源代码的最大优势是 PORTABILITY

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

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

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

答案 6 :(得分:7)

编译器和解释器执行相同的工作:将编程语言翻译成另一种通常更接近硬件的pgoramming语言,通常指向可执行的机器代码。

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

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

但是现在“编译与解释”并不是一个黑白问题,其间存在阴影。天真,简单的口译员已经灭绝了。许多语言使用两步过程,其中高级代码被转换为平台无关的字节码(解释速度快得多)。然后你有“及时编译器”,每次程序运行最多编译一次代码,有时会缓存结果,甚至智能地决定解释很少运行的代码,并对运行很多的代码进行强大的优化。在开发过程中,即使对于传统的编译语言,调试器也能够在正在运行的程序中切换代码。

答案 7 :(得分:4)

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

更重要的是:我认为互动是主要的实际差异。由于所有内容都被解释,您可以采用一小段代码,解析并针对当前环境状态运行它。因此,如果您已经执行了初始化变量的代码,那么您将可以访问该变量等。它真正适用于功能样式等。

然而,解释成本很高,特别是当你有一个包含大量引用和上下文的大型系统时。根据定义,它是浪费的,因为相同的代码可能必须被解释和优化两次(尽管大多数运行时都有一些缓存和优化)。但是,您需要支付运行时成本并且通常需要运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能不够充分。

因此,对于不会发生太大变化的大型系统,对于某些语言,预编译和预链接所有内容更有意义,可以执行所有可以执行的优化。这最终得到了一个非常精简的运行时,它已经针对目标机器进行了优化。

至于生成可执行程序,这与它几乎没有关系,恕我直言。您通常可以从编译语言创建可执行文件。但是您也可以从解释语言创建可执行文件,除了解释器和运行时已经打包在exectuable中并且对您隐藏。这意味着您通常仍然需要支付运行时成本(尽管我确信某些语言可以将所有内容转换为树可执行文件)。

我不同意所有语言都可以互动。某些语言,如C,如此依赖于机器和整个链接结构,我不确定您是否可以构建一个有意义的完全成熟的交互式版本

答案 8 :(得分:2)

提供实际答案相当困难,因为区别在于语言定义本身。可以为每种编译语言构建解释器,但是不可能为每种解释语言构建编译器。它非常关乎语言的正式定义。因此理论信息学的东西在大学里喜欢noboby。

答案 9 :(得分:2)

Python Book©2015 Imagine Publishing Ltd,简单地通过第10页中提到的以下提示来区分差异:

  

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

答案 10 :(得分:1)

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

答案 11 :(得分:0)

差异

翻译:

1)处理:解释器从程序产生结果。 (在运行程序时将程序转换为机器代码)另一方面,在已解释程序中,源代码通常是程序。这种类型的程序(通常称为脚本)需要解释器,该解释器将解析程序中的命令,然后执行它们。一些解释器(例如Unix shell(sh,csh,ksh等))读取并立即执行每个命令,而其他解释器(例如Perl)则在发送相应的机器语言指令之前分析整个脚本。解释语言的其他示例包括JavaScript和Python。

2)快速开发(编辑和运行)。

3)执行缓慢,因为每个语句每次执行时都必须将其解释为机器代码(想想这对于执行数千次循环意味着什么)。

4)如果对源代码进行了解释,则只需编写一次即可,并且可以在任何平台上由适当的解释器对其进行解释和执行!

5)使用解释器的一个缺点是它不会向最终用户隐藏源代码

6)继续翻译程序,直到遇到第一个错误为止,在这种情况下它将停止。因此调试很容易。

编译器:

1)处理:(在程序运行之前将程序转换为机器代码)而编译器生成用汇编语言编写的程序。然后,体系结构的汇编程序将生成的程序转换为二进制代码。汇编语言对于每台单独的计算机而言都不同,具体取决于其体系结构。因此,编译后的程序只能在与编译它们的计算机具有相同体系结构的计算机上运行。 编译后的程序不是人类可读的,而是使用特定于体系结构的机器语言。创建一个已编译的程序需要几个步骤。首先,程序员使用开发工具或简单的文本编辑器,以选定的计算机语言编写源代码。如果程序很复杂,它的各个部分可能会分散在多个文件中。然后,程序员编译程序,对模块进行分类和链接,然后将其全部翻译为计算机可以理解的机器代码。由于不同种类的计算机不会说彼此的机器语言,因此编译后的程序只能在为其设计的平台上运行。例如,为HP-UX编写的程序通常无法在Mac OS计算机或运行Solaris的计算机上运行。

2)开发缓慢(编辑,编译,链接和运行。编译/链接步骤可能需要花费大量时间)。

3)快速执行。整个程序已经在本地机器代码中。

4)编译后的程序只能在其设计平台上运行。它不是便携式的

5)编译代码的一个优点是,它向最终用户隐藏了源代码(可能是知识产权),因为您部署了晦涩的二进制可执行文件,而不是部署原始的人类可读源代码。 6)仅在扫描整个程序后才生成错误消息。因此,调试相对困难。

来源: * https://kb.iu.edu/d/agsz *这篇文章中的不同答案

答案 12 :(得分:0)

(不精确的)简短定义:

编译语言:整个程序立即转换为机器代码,然后由CPU运行机器代码。

解释性语言::逐行读取程序,一旦读取一行,CPU就会执行该行的机器指令。

但是,实际上,目前很少有语言是纯粹编译或纯粹解释的,通常是混合使用的。有关图片的详细说明,请参见此线程:

What is the difference between compilation and interpretation?

或者我以后的博客文章:

https://orangejuiceliberationfront.com/the-difference-between-compiler-and-interpreter/