Ordre d'évaluation en PHP

Note du traducteur. Nikita Popov a fait et continue d'apporter une énorme contribution au développement du langage PHP. Il comprend très bien les éléments internes du moteur PHP et dans cet article il explique certaines des fonctionnalités de PHP en termes d'ordre d'évaluation des expressions, qui, peut-être, ne se trouvent pas particulièrement nulle part. Cet article a environ 7 ans et n'a pratiquement pas perdu de sa pertinence, cependant, il est assez difficile de le trouver, car il n'est pas dans le blog de Nikita Popov, mais il a été publié dans son essentiel sur github. Je pense qu'il sera utile de le présenter à la communauté en russe.



Dans ma communauté reddit préférée, lolphp, je suis tombé sur un article où les gens sont surpris du résultat du code suivant:



<?php

$a = 1;
$c = $a + $a++;
var_dump($c); // int(3)

$a = 1;
$c = $a + $a + $a++;
var_dump($c); // int(3)


Comme vous pouvez le voir, les expressions ($a + $a++)et ($a + $a + $a++)donnent le même résultat, ce qui est assez inattendu. Que se passe t-il ici?



Priorité et associativité des opérateurs



Beaucoup de gens pensent que l'ordre dans lequel une expression est évaluée est déterminé par la priorité et l'associativité des opérateurs , mais ce n'est pas le cas. La priorité et l'associativité déterminent uniquement l'ordre dans lequel les opérations sont regroupées dans une expression.

Dans la première expression, le $c = $a + $a++;post-incrémentation "++" a priorité sur "+", donc $ a ++ est un groupe séparé:



$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. L'opérateur @désactive l'optimisation CV et dégrade les performances en conséquence. L'opérateur est, @en principe, mauvais pour les performances.


~ nikic



Note du traducteur: comme mentionné ci-dessus, il ne @désactive les optimisations de CV qu'en 5.x, en PHP 7, les optimisations de CV ont lieu même si l'opérateur de suppression d'erreur est utilisé (mais peut-être que cela ne se produit pas dans tous les cas). Nikita Popov a un article de blog intéressant, Static Optimization in PHP 7 , au cas où quelqu'un voudrait approfondir le sujet de l'optimisation.




All Articles