Nota do tradutor. Nikita Popov fez e continua a dar uma grande contribuição para o desenvolvimento da linguagem PHP. Ele entende a parte interna do motor PHP muito bem e neste artigo ele explica alguns dos recursos do PHP em termos de avaliação da ordem de expressão, que, talvez, não sejam particularmente encontrados em qualquer lugar. Este artigo tem cerca de 7 anos e praticamente não perdeu sua relevância, no entanto, é bastante difícil encontrá-lo, pois não está no blog de Nikita Popov, mas foi publicado em seus gist-s no github. Acho que será útil apresentá-lo à comunidade em russo.
Na minha comunidade favorita do reddit lolphp , encontrei um post em que as pessoas ficam surpresas com o resultado do seguinte código:
<?php
$a = 1;
$c = $a + $a++;
var_dump($c); // int(3)
$a = 1;
$c = $a + $a + $a++;
var_dump($c); // int(3)
Como você pode ver, expressões ($a + $a++)
e ($a + $a + $a++)
dar o mesmo resultado, o que é bastante inesperada. O que está acontecendo aqui?
Precedência e associatividade do operador
Muitas pessoas pensam que a ordem em que uma expressão é avaliada é determinada pela precedência e associatividade dos operadores , mas este não é o caso. A prioridade e a associatividade determinam apenas a ordem em que as operações são agrupadas em uma expressão.
Na primeira expressão, o $c = $a + $a++;
pós-incremento "++" tem precedência sobre "+", portanto $ a ++ é um grupo separado:
$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.
- , :
- . .
- O operador
@
desativa a otimização de CV e degrada o desempenho como resultado. O operador é,@
em princípio, ruim para o desempenho.
~ nikic
Nota do tradutor: como foi dito acima, ele @
desabilita as otimizações de CV apenas em 5.x, no PHP 7 as otimizações de CV ocorrem mesmo se o operador de supressão de erro for usado (mas talvez isso não aconteça em todos os casos). Nikita Popov tem um post interessante no blog, Static Optimization in PHP 7 , caso alguém queira se aprofundar no tópico de otimização.