难道他们都不得不在某个时刻转换为机器代码才能执行,或者我错过了哪些更基本的东西?
编辑:
请考虑更复杂的口译方案,例如将代码转换为字节代码并且仅在源代码改变时重新生成字节代码的情况,例如CPython实现Python? 我对那些逐行重新执行的古代翻译并不感兴趣....
谢谢!
答案 0 :(得分:17)
像C这样的编译语言通常直接编译为机器代码。运行代码时,它由CPU直接执行。
每次运行时,通常会解释像BASIC或PHP这样的完全解释语言。执行代码时,CPU执行解释器,解释器读取并执行源代码。 (PHP可以归类为完全解释,因为虽然它确实使用操作码,但它们通常在执行后被丢弃。)
像Python这样的字节码解释语言,从源代码编译为由虚拟机执行的字节码。 CPU运行VM,VM执行每个字节码指令。在Python中,字节码是在第一次执行代码时编译的。
在Java中,字节码在执行之前编译。 Java VM还有一个称为即时编译的特殊功能。这意味着在执行期间,它可以将一些字节码编译为机器码,它可以发送到CPU直接执行。
总之,使用编译语言,CPU直接运行代码。在解释型语言中,CPU通常运行解释器或虚拟机。由于运行VM或解释器的开销,这使得解释语言通常比编译语言慢。
注意:虽然我们谈到解释和编译的语言,但我们真正讨论的是语言的常用执行风格。可以编译PHP(使用HipHop),并且可以解释C(使用Parrot VM)。
答案 1 :(得分:5)
好的,这里有很多不正确的帖子,时间很长。
编译器基本上是清晰的 - 它将源语言的程序转换为目标语言。两种语言都可以是任何语言 - 高级语言,虚拟机字节码,机器代码。
另一方面,解释器不执行翻译,但是直接执行源语言构造规定的动作,也就是解释它。
让我们考虑基于堆栈的机器中的假设add
指令,它添加堆栈的两个顶部元素并将结果推回。解释器将直接执行“添加两个顶部元素并将结果推回”,方式类似于:
switch (op)
{
....
case OP_ADD:
op1 = pop (stack);
op2 = pop (stack);
res = op1 + op2;
push (stack, res);
break;
...
}
正如您所看到的,对于单个add
insn,执行了许多操作:读取和写入内存,递增和递减堆栈指针,添加操作本身,交换机的开销(如果解释器)以这种方式实现),循环的开销,读取每个后续insn并决定如何处理它等。
如果插件工作在AST上,它可能看起来像:
swicth (op)
{
...
case OP_ADD:
op1 = tree->eval (left);
op2 = tree->eval (right);
return op1 + op2;
...
}
同样,很多很多insn执行add
语义所需的任何内容。
答案 2 :(得分:3)
在运行程序之前,编译器会将程序转换为机器代码。它在编译时解析所有变量,类型。
每次执行语句时,解释器通常会将每个语句转换为机器代码。
答案 3 :(得分:3)
编辑和解释之间的界限模糊。通常,一些形式的解释比直接编译的代码工作得慢。在具体情况下可能不一定如此。
例如,一些解释器直接执行虚拟机指令(有时会转换为直接或间接的线程代码),由于显而易见的原因,它比本机代码慢。
由于VM的语义之间存在阻抗不匹配(例如,它们中的大多数是基于堆栈的)和本机代码的语义,因此从一个到另一个的任何ad hoc转换将是次优的。为了执行重量级优化,您需要一个虚拟机(或任何其他形式的中间表示),其中包含一定数量的目标平台特定语义。 LLVM就是这种表示的一个很好的例子。
其他一些解释器甚至在抽象语法树级别上评估代码。有些人正在执行字符串替换(一个臭名昭着的例子是Tcl)。
所有这些技术都很容易实现,它们为语言语义提供了一些有趣的动态属性,但都以较慢的执行速度为代价。
另一个重要的事情是supercompilation。通过将解释器实现专门针对要执行的代码的特定实例,该技术实际上将任何解释器转换为编译器。这种方法的存在使得编译和解释之间的差异更加模糊。
答案 4 :(得分:1)
根据WikiPedia:
解释代码比运行已编译的代码慢,因为解释器必须在每次执行时分析程序中的每个语句,然后执行所需的操作,而编译的代码只是在由编译确定的固定上下文中执行操作。此运行时分析称为“解释开销”。在解释器中访问变量的速度也较慢,因为标识符到存储位置的映射必须在运行时而不是在编译时重复进行。
答案 5 :(得分:0)
编译器执行一次(这需要一些时间),然后代码运行得很快。 因为它可能需要很长时间,它也可能花费相当多的时间来优化代码。
解释器在您想要运行代码时执行此操作,因此每次运行时都会编译它。
答案 6 :(得分:0)
Interpreter逐行执行,并在运行时将每一行转换为机器指令。而编译器在编译时中将整个程序从源语言转换为目标语言(最可能是目标处理器的机器指令)。