chi*_*der 263 python java compiler-construction interpreter programming-languages
我正在努力更好地理解这种差异.我在网上找到了很多解释,但它们倾向于抽象的差异而不是实际的含义.
我的大部分编程经验都是CPython(动态,解释)和Java(静态,编译).但是,据我所知,还有其他类型的解释和编译语言.除了可执行文件可以从编译语言编写的程序中分发之外,每种类型都有任何优点/缺点吗?通常,我听到有人认为解释性语言可以交互使用,但我相信编译语言也可以有交互式实现,对吗?
mik*_*era 437
编译语言是程序一旦编译就在目标机器的指令中表达的语言.例如,源代码中的附加"+"操作可以直接转换为机器代码中的"ADD"指令.
一种解释语言是其中所述指令不被目标机器直接执行,而是读取和执行通过一些其它方案(其通常被写入本机机器的语言).例如,解释器在运行时将识别相同的"+"操作,然后将使用适当的参数调用其自己的"add(a,b)"函数,然后执行机器代码"ADD"指令.
您可以使用编译语言以解释语言执行任何操作,反之亦然 - 它们都是图灵完备的.然而,两者都具有实施和使用的优点和缺点.
我将完全概括(纯粹主义者原谅我!)但是,粗略地说,这是编译语言的优点:
以下是解释语言的优点:
请注意,现代技术(如字节码编译)会增加一些额外的复杂性 - 这里发生的是编译器针对的是与底层硬件不同的"虚拟机".然后可以在稍后阶段再次编译这些虚拟机指令以获得本机代码(例如,由Java JVM JIT编译器完成).
lun*_*orn 95
语言本身既不编译也不解释,只是语言的特定实现.Java就是一个很好的例子.有一个基于字节码的平台(JVM),一个本机编译器(gcj)和一个Java超集(bsh)的插件.那么Java现在是什么?字节码编译,本地编译或解释?
其他编译和解释的语言是Scala,Haskell或Ocaml.这些语言中的每一种都有一个交互式解释器,以及字节码或本机机器码的编译器.
因此,通常按"编译"和"解释"对语言进行分类并没有多大意义.
Nea*_*alB 51
从过去开始思考:爆炸
曾几何时,很久很久以前,那里住着计算机翻译和编译器.随着一个人的优点,各种各样的烦恼随之而来.普遍的观点在当时是沿着线的东西:
解释程序和编译程序之间存在一个或两个数量级的运行时性能差异.其他区别点,例如代码的运行时可变性,也有一些兴趣,但主要区别在于运行时性能问题.
今天,景观已发展到如此程度,以至于编译/解释的区别几乎无关紧要.许多编译语言都会调用不完全基于机器代码的运行时服务.此外,大多数解释语言在执行之前被"编译"为字节码.字节码解释器可以非常高效,并且从执行速度的角度来看与一些编译器生成的代码相匹敌.
经典的区别在于编译器使用某种运行时系统生成本机机器代码,解释器读取源代码并生成机器代码.今天很少有经典的解释器 - 几乎所有解释器都编译成字节码(或其他一些半编译状态),然后在虚拟"机器"上运行.
Car*_*icz 25
极端简单的案例:
编译器将以目标机器的本机可执行格式生成二进制可执行文件.此二进制文件包含除系统库之外的所有必需资源; 它已准备好运行而无需进一步的准备和处理,它像闪电一样运行,因为代码是目标机器上CPU的本机代码.
解释器将在循环中向用户显示提示,在该循环中他可以输入语句或代码,并且在敲击RUN
或等效时,解释器将检查,扫描,解析和解释性地执行每一行,直到程序运行到停止点或错误.因为每一行都是自己处理的,并且解释器没有"学习"任何东西,因为之前已经看过该行,所以每次为每一行都会产生将人类可读语言转换为机器指令的努力,因此它的速度很慢.从好的方面来说,用户可以通过各种方式检查和以其他方式与他的程序交互:更改变量,更改代码,以跟踪或调试模式运行......等等.
有了这些,让我解释说生活不再那么简单了.例如,
最后,现在,解释与编译是一种权衡,花费的时间(一次)编译通常会得到更好的运行时性能的奖励,但解释性环境会提供更多的交互机会.编译与解释主要是关于"理解"程序的工作如何在不同的流程之间划分的问题,而且现在这条线路有点模糊,因为语言和产品试图提供两全其美的优势.
Bha*_*hah 20
来自http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages
没有区别,因为"编译编程语言"和"解释编程语言"并不是有意义的概念.任何编程语言,我的意思是任何,都可以被解释或编译.因此,解释和编译是实现技术,而不是语言的属性.
解释是一种技术,其中另一个程序,即解释器,代表正在解释的程序执行操作以便运行它.如果你可以想象阅读一个程序并按照它所说的一步一步做,就像在一张草稿纸上说的那样,那就是翻译所做的.解释程序的一个常见原因是解释器相对容易编写.另一个原因是,解释器可以监视程序在运行时尝试执行的操作,以实施策略,例如安全性.
编译是一种技术,用一种语言("源语言")编写的程序被翻译成另一种语言的程序("对象语言"),这有望与原始程序相同.在进行转换时,编译器也常常尝试以使对象程序更快的方式转换程序(不改变其含义!).编译程序的一个常见原因是,有一些很好的方法可以快速运行目标语言中的程序,而且不会产生解释源语言的开销.
根据上述定义,您可能已经猜到这两种实现技术并不是相互排斥的,甚至可能是互补的.传统上,编译器的目标语言是机器代码或类似的东西,它指的是特定计算机CPU理解的任何数量的编程语言.然后机器代码将"在金属上"运行(尽管人们可能会看到,如果足够仔细地看,"金属"的工作方式很像解释器).然而,今天,使用编译器生成要解释的目标代码是很常见的 - 例如,这就是Java过去(有时仍然如此)工作的方式.有些编译器会将其他语言翻译成JavaScript,然后通常在Web浏览器中运行,这可能会解释JavaScript,或者将其编译为虚拟机或本机代码.我们还有机器代码的解释器,可用于在另一个上模拟一种硬件.或者,可以使用编译器生成目标代码,然后该代码是另一个编译器的源代码,它甚至可以及时编译内存中的代码以便运行,反过来...你明白了.有很多方法可以将这些概念结合起来.
Nik*_*lic 10
解释源代码优于已编译源代码的最大优点是可移植性.
如果您的源代码已编译,则需要为您希望程序运行的每种类型的处理器和/或平台编译不同的可执行文件(例如,一个用于Windows x86,一个用于Windows x64,一个用于Linux x64,等等上).此外,除非您的代码完全符合标准并且不使用任何特定于平台的函数/库,否则您实际上需要编写和维护多个代码库!
如果您的源代码被解释,您只需要编写一次,它可以由任何平台上的相应解释器解释和执行!它便于携带!注意,解释器本身是一个可执行程序的编写和编译为特定平台.
编译代码的一个优点是它隐藏了最终用户的源代码(可能是知识产权),因为您不是部署原始的人类可读源代码,而是部署一个不起眼的二进制可执行文件.
编译器和解释器执行相同的工作:将编程语言翻译成另一种通常更接近硬件的pgoramming语言,通常指向可执行的机器代码.
传统上,"编译"意味着这种翻译一次完成,由开发人员完成,并将生成的可执行文件分发给用户.纯粹的例子:C++.编译通常需要很长时间,并尝试进行大量昂贵的optmization,以便生成的可执行文件运行得更快.最终用户没有自己编译内容的工具和知识,并且可执行文件通常必须在各种硬件上运行,因此您无法进行许多特定于硬件的优化.在开发期间,单独的编译步骤意味着更长的反馈周期.
传统上,"解释"意味着当用户想要运行程序时,翻译"在运行中"发生.纯粹的例子:香草PHP.天真的解释器必须在每次运行时解析和翻译每段代码,这使得它非常慢.它不能进行复杂,昂贵的优化,因为它们花费的时间比执行时节省的时间长.但它可以充分利用其运行的硬件的功能.缺乏separrate编译步骤减少了开发期间的反馈时间.
但是现在"编译与解释"并不是一个黑白问题,中间有阴影.天真,简单的口译员已经灭绝了.许多语言使用两步过程,其中高级代码被转换为平台无关的字节码(解释速度快得多).然后你有"及时编译器",每次程序运行最多编译一次代码,有时会缓存结果,甚至智能地决定解释很少运行的代码,并对运行很多的代码进行强大的优化.在开发期间,调试器能够在正在运行的程序中切换代码,即使对于传统编译语言也是如此.
我猜这是计算机科学中最大的误解之一。因为解释和编译是完全不同的两个东西,我们不能这样比较。
机器级解释 - 这种解释发生在编译成机器代码的代码上。指令由处理器直接解释。C/C++ 等编程语言生成可由处理器执行的机器代码。所以处理器可以直接执行这些指令。
虚拟机级别解释 - 这种解释发生在未编译为机器级别(处理器支持)代码,而是编译为某些中间级别代码的代码。该执行是由另一个软件完成的,该软件由处理器执行。此时实际上处理器并没有看到我们的应用程序。它只是执行虚拟机,虚拟机正在执行我们的应用程序。Java、Python、C# 等编程语言生成字节码,可由虚拟解释器/机器执行。
所以最终我们必须明白的是,世界上所有的编程语言都应该在某个时候被解释。它可以由处理器(硬件)或虚拟机来完成。
编译只是将我们编写的人类可理解的高级代码提升到某种硬件/软件机器可理解的级别的过程。
这是完全不同的两个事情,我们无法比较。但这个术语对于教导初学者编程语言如何工作非常有用。
PS:
一些编程语言(例如 Java)有一种混合方法来执行此操作。首先,将高级代码编译为虚拟机可读的字节代码。一个称为 JIT 编译器的组件会即时将字节码编译为机器代码。具体来说,多次执行的代码行会被翻译成机器语言,这使得解释过程更快。因为硬件处理器总是比虚拟解释器/处理器快得多。
首先,澄清一下,Java 不是完全静态编译和以 C++ 的方式链接的。它被编译成字节码,然后由 JVM 解释。JVM 可以对本地机器语言进行即时编译,但并非必须这样做。
更重要的是:我认为交互性是主要的实际区别。由于所有内容都被解释,您可以提取一小段代码,针对当前环境状态解析并运行它。因此,如果您已经执行了初始化变量的代码,您将可以访问该变量等。它确实适用于诸如函数式风格之类的事情。
然而,解释的成本很高,尤其是当您拥有一个包含大量参考资料和上下文的大型系统时。根据定义,这是一种浪费,因为相同的代码可能必须被解释和优化两次(尽管大多数运行时都为此进行了一些缓存和优化)。尽管如此,您仍需支付运行时成本,并且通常需要一个运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能不够交互。
因此,对于不会有太大变化的大型系统,对于某些语言,预编译和预链接所有内容,做所有可以做的优化更有意义。这最终会得到一个非常精简的运行时,该运行时已经针对目标机器进行了优化。
至于生成可执行文件,恕我直言,这与它无关。您通常可以从编译语言创建可执行文件。但是您也可以从解释性语言创建可执行文件,只是解释器和运行时已经打包在可执行文件中并且对您隐藏。这意味着您通常仍然需要支付运行时成本(尽管我确信对于某些语言,有办法将所有内容转换为树可执行文件)。
我不同意所有语言都可以交互。某些语言,例如 C,与机器和整个链接结构如此紧密地联系在一起,我不确定您是否可以构建一个有意义的成熟的交互式版本
归档时间: |
|
查看次数: |
203223 次 |
最近记录: |