PHP是编译还是解释的?


142

PHP是编译还是解释的?

Answers:


127

PHP是一种解释型语言。使您可以解释PHP的二进制文件已编译,但是您编写的内容得到了解释。

您可以在Wikipedia页面上看到更多有关口译语言的信息


26
他表示称为php的实用程序(或在Windows php.exe上)已编译。
sepp2k

7
@nicky表示已编译用于解释PHP的程序,但解释了PHP本身。
安德鲁·宋

5
但是,为什么它在维基百科中如此提及?goo.gl/YOwZ 从PHP 4开始,PHP解析器编译输入以生成字节码以供Zend Engine处理,从而使其解释器的性能有所提高。
kiranvj 2012年

5
@kiranvj确实已编译以提高性能,但在运行时。将“编译语言”视为“预编译”,将解释语言视为“运行时已编译”。这是两者之间的区别:-JIT(“及时”),在需要时仅编译所需的代码(但是请注意,在解释器退出后,已编译的代码很多)-AOT(“提前”),所有代码都在运行之前进行编译。
Thibault Martin-Lagardette 2012年

4
@kiranvj:我相信OP希望知道PHP是否已编译为本机代码。就编译成本和运行时性能而言,将其编译为字节码,然后由Zend再次解释为字节码。大声笑,这是一个相当古老的线程,只是意识到这一点。
Groo 2012年

66

都。PHP被编译为中间字节码,然后由运行时引擎解释。

PHP编译器的工作是解析您的PHP代码,并将其转换为适合运行时引擎的形式。其任务包括:

  • 忽略评论
  • 解析变量,函数名称等,并创建符号表
  • 构造程序的抽象语法树
  • 写字节码

根据您的PHP设置,此步骤通常在第一次调用脚本时仅执行一次。缓存编译器输出以加快后续使用的访问速度。但是,如果脚本被修改,则再次执行编译步骤。

调用脚本时,运行时引擎将遍历AST和字节码。符号表用于存储变量的值并提供函数的字节码地址。

对于在某种虚拟运行时机器(包括Perl,Java,Ruby,Smalltalk等)上运行的语言而言,这种编译为字节码并在运行时进行解释的过程是典型的。


变量绑定发生在运行时,而不是编译时。
jrockway

PHP甚至没有尝试在编译时解析哪些名称在范围内?
巴里·布朗

17

通常,它是可解释的,但是一段时间可以将其用作已编译的,并且确实可以提高性能。开源工具来执行此操作:hhvm.com


15

PHP是一种解释型语言。但是,可以通过第三方工具将其编译为字节码。


2
“字节码”是用于VM特定伪指令的术语,它不是本机的,因此在这种情况下不能被视为“编译”。
Sedat Kapanoglu,2009年

7
“目标代码”只是CPU指令解码器的字节码。(您不认为CPU实际上具有诸如“ CMPSB”之类的本机指令,对吗?)
jrockway,2009年

11

一个编译后的代码可以直接通过电脑的CPU来执行。即,以CPU的本地语言指定可执行代码。

解释语言的代码必须在运行时从任何格式转换为CPU机器指令。该翻译由口译员完成。

不能说一种语言是解释性或编译性的,因为解释性和编译性都是该特定语言实现属性,而不是该语言本身的属性。因此,任何语言都可以编译或解释-这仅取决于您所使用的特定实现。

最广泛使用的PHP实现由Zend Engine提供支持,并简称为PHP。ZendEngine将PHP源代码编译为可以执行的格式,因此Zend Engine充当解释器


2
也就是说,可执行代码是用CPU的本机语言指定的。 ”。可执行代码不是用CPU的本机语言指定的,而是二进制格式,CPU的本机语言可以是任何东西,并且当软件二进制文件不适合这种情况时, CPU或那个CPU ..完全编译且可执行的代码将采用二进制格式..
hagrawal

10

这是一个毫无意义的问题。与GCC一样,PHP使用yacc(野牛)。yacc是一个“编译器编译器”。yacc的输出是一个编译器。编译器的输出是“已编译”。PHP由yacc的输出解析。因此,按照定义,它已编译。

如果不满意,请考虑以下事项。php(二进制)和gcc均读取您的源代码并生成抽象语法树。在版本4和5下,php然后遍历树将程序转换为字节码(编译步骤)。您可以看到使用Vulcan Logic Dumper将字节码转换为操作码(类似于汇编)。最后,php(特别是Zend引擎)解释字节码。相比之下,gcc走树并输出程序集;它还可以运行汇编器和链接器以完成该过程。调用由一个“解释的”处理的程序和由另一个“已编译的”处理的另一个程序是没有意义的。毕竟,程序都通过两者的“编译器”运行。

实际上,您应该问自己想问的问题。(“由于PHP为每个请求重新编译我的源代码,我是否要付出性能损失?”等)


5
标记源代码未编译。即使您定义了VBScript,也可以将其视为已编译的语言。
Sedat Kapanoglu,2009年

5
我对此表示赞同,尽管它并不能真正回答OP的问题。试图创建一种语言分类法,将每种语言整齐地放置在每个类别中。但是现实并不是那么整洁。几乎每种语言都是特征的融合。另外,当您深入研究它时,即使是本机代码也会被处理器“解释”。
巴里·布朗

4
您的高级断言是正确的,这一个毫无意义的问题。但是,您的论点不是很有帮助,您所做的只是采用模糊的定义并将其达到极限。编译是将源代码转换为目标代码。是的,您可以考虑将源代码转换为具体/抽象语法树的编译,但这不是大多数人的意思吗?无论如何,这是一个毫无意义的问题,因为语言不是固有地编译或解释的,语言的实现是编译或解释的。
Falaina

6
让我们不要监督那个家伙是初学者。这使我将问题解释为“ Zend实现是否从PHP源代码中生成本机代码?”。查看我的答案。我认为您对问题的提出方式过于严格。您知道,我们正在努力提供帮助,而不是抨击一些新手。
Sedat Kapanoglu,2009年

3
我完全同意塞达特。您可以分享自己的知识,而不必高加索取
Alexandre Bourlier's

10

我知道这个问题很旧,但是到处都有联系,我认为这里的所有答案都不正确(也许是因为它们很旧)。

NO作为一种解释语言或编译语言这样的事情。可以解释和/或编译任何编程语言。

首先,一种语言只是一组规则,所以当我们谈论编译时,我们指的是该语言的特定实现

例如,HHVM是PHP的实现。它使用JIT编译将代码转换为中间的HipHop字节码,然后转换为机器码。说它已编译就足够了吗?一些Java实现(并非全部)也使用JIT。Google的V8也使用JIT。

如今,使用已编译与已解释的旧定义已无济于事。

“ PHP是否已编译?” 鉴于在已编译语言与已解释语言之间不再存在明确且一致的定界符,这是一个荒谬的问题。

分隔它们的一种可能方法是(在这种二分法中我找不到任何含义):

编译语言使用Ahead of Time编译(C,C ++);

解释语言使用即时编译或根本不编译(Python,Ruby,PHP,Java)。


但是,在大多数情况下,Java是否不使用提前编译?我是一个相当新的Java开发人员,我们通常在运行时之前编译我们的代码。
aCarella

@aCarella in most cases,是的。在所有情况下,都不是。因此,您不能划出一条在语义上有意义且一致的线。
Claudiu Creanga

2

至少它不会像人们想要的那样编​​译(或应该说优化)代码。

此代码...

for($i=0;$i<100000000;$i++);
echo $i;

...在每次运行时都会使程序延迟相等。

它可能已经检测到这是只需要第一次进行的计算。


现在我们有一个称为生成器的选项。
Ankit Vishwakarma

1

公认的答案显然是错误的。PHP已编译。故事结局。也许不是本地指令,而是解释后的字节码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.