Translator's note. Nikita Popov has made and continues to make a huge contribution to the development of the PHP language. He understands the internals of the PHP engine very well and in this article he explains some of the features of PHP in terms of the order of expression evaluation, which, perhaps, are not particularly found anywhere. This article is about 7 years old and has practically not lost its relevance, however, it is rather difficult to find it, because it is not in Nikita Popov's blog, but it was published in his gist-s on github. I think it will be useful to present it to the community in Russian.
In my favorite Reddit community lolphp I came across a post where people are surprised at the result of the following code:
<?php
$a = 1;
$c = $a + $a++;
var_dump($c); // int(3)
$a = 1;
$c = $a + $a + $a++;
var_dump($c); // int(3)
As you can see, expressions ($a + $a++)
and ($a + $a + $a++)
give the same result, which is quite unexpected. What's going on here?
Operator precedence and associativity
Many people think that the order in which an expression is evaluated is determined by operator precedence and associativity , but this is not the case. Priority and associativity only determine the order in which operations are grouped in an expression.
In the first expression, $c = $a + $a++;
post-increment "++" takes precedence over "+", so $ a ++ is a separate group:
$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.
- , :
- . .
- The operator
@
disables CV optimization and degrades performance as a result. The operator is,@
in principle, bad for performance.
~ nikic
Translator's note: as mentioned above, it @
disables CV optimizations only in 5.x, in PHP 7 CV optimizations take place even if the error suppression operator is used (but perhaps this does not happen in all cases). Nikita Popov has an interesting blog post, Static Optimization in PHP 7 , in case someone wants to dig deeper into the topic of optimization.