译者注。Nikita Popov为PHP语言的发展做出了并将继续做出巨大贡献。他非常了解PHP引擎的内部原理,在本文中,他根据表达式求值的顺序解释了PHP的一些功能,这些表达式可能在任何地方都找不到。这篇文章大约有7年历史了,实际上并没有失去它的相关性,但是,很难找到它,因为它不在Nikita Popov的博客中,而是在gis-s的github上发布的。我认为将其呈现给俄语社区会很有用。
在我最喜欢的reddit社区lolphp中,我遇到了一个帖子,人们对以下代码的结果感到惊讶:
<?php
$a = 1;
$c = $a + $a++;
var_dump($c); // int(3)
$a = 1;
$c = $a + $a + $a++;
var_dump($c); // int(3)
如您所见,表达式($a + $a++)
和($a + $a + $a++)
给出相同的结果,这是非常意外的。这里发生了什么?
运算符优先级和关联性
许多人认为,对表达式求值的顺序由运算符的优先级和关联性决定,但事实并非如此。优先级和关联性仅确定表达式中操作分组的顺序。
在第一个表达式中,$c = $a + $a++;
后递增“ ++”优先于“ +”,因此$ a ++是一个单独的组:
$c = $a + ($a++);
$c = $a + $a + $a++;
- "++" , "+":
$c = $a + $a + ($a++);
"+" - , "+" :
$c = ($a + $a) + ($a++);
: , .
? . , , . , , ($a + $a)
, ($a++)
.
PHP . PHP , — . , - .
CV
-, , PHP , , ( PHP).
(compiled variables, CV), PHP 5.1. (, $a
, $a->b
$a['b']
) . — , PHP , Zend VM ( Zend). 2 .
, .
$a + $a + $a++
:
// code:
$a = 1;
$c = ($a + $a) + ($a++);
// opcodes:
ASSIGN $a, 1
$tmp_1 = ADD $a, $a
$tmp_2 = POST_INC $a
$tmp_3 = ADD $tmp_1, $tmp_2
ASSIGN $c, $tmp_3
:
-
$a = 1
, - —
$a + $a
$tmp_1
, - -
$a
$tmp_2
, - , ,
$c
.
( $a + $a
, $a++
), , , .
$a + $a++
:
// code:
$a = 1;
$c = $a + ($a++);
// opcodes:
ASSIGN $a, 1
$tmp_1 = POST_INC $a
$tmp_2 = ADD $a, $tmp_1
ASSIGN $c, $tmp_2
, POST_INC ($a++)
, $a
ADD
. ? . . CV .
CV
: , CV - @
. PHP 5.x, PHP 7 . , PHP 5 , , - - CV CV.
() , CV , , @
.
. $a + $a++
, , @
:
<?php
$a = 1;
@ $c = $a + $a++;
var_dump($c); // int(2)
, , 3 2. , :
ASSIGN $a, 1
$tmp_1 = BEGIN_SILENCE
$var_3 = FETCH_R 'a'
$tmp_4 = POST_INC $a
$tmp_5 = ADD $var_3, $tmp_4
$var_2 = FETCH_W 'c'
ASSIGN $var_2, $tmp_5
END_SILENCE $tmp_1
, . -, BEGIN_SILENCE
END_SILENCE
. . -, $a
$b
FETCH_R
( ) FETCH_W
( ) .
, $a
, .
CV , , .
. $a + $a++
, :
<?php
$a = [1];
$c = $a[0] + $a[0]++;
var_dump($c); // int(2)
, , 3 2. , :
ASSIGN $a, [1]
$tmp_3 = FETCH_DIM_R 'a', 0
$var_4 = FETCH_DIM_RW 'a', 0
$tmp_5 = POST_INC $var_4
$tmp_6 = ADD $tmp_3, $tmp_5
ASSIGN $c, $tmp_6
, FETCH_DIM_R
( ) FETCH_DIM_RW
( /) .
, , , .
, . 3v4l.org.
- , :
- . .
- 操作员
@
禁用CV优化并因此降低性能。原则上,操作员@
不利于性能。
〜尼克
译者注:如前所述,它@
仅在5.x中禁用CV优化,在PHP 7中,即使使用了错误抑制运算符,也会进行CV优化(但可能并非在所有情况下都如此)。Nikita Popov有一篇有趣的博客文章,《PHP 7中的静态优化》,以防有人想深入研究优化主题。