Ordem de avaliação em PHP

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.



PHP 5.x

() , 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.





- , :



  1. . .
  2. 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.




All Articles