Auswertungsreihenfolge in PHP

Anmerkung des Übersetzers. Nikita Popov hat einen großen Beitrag zur Entwicklung der PHP-Sprache geleistet und leistet dies auch weiterhin. Er versteht die Interna der PHP-Engine sehr gut und erklärt in diesem Artikel einige der Funktionen von PHP in Bezug auf die Reihenfolge der Ausdrucksbewertung, die vielleicht nirgendwo anders zu finden sind. Dieser Artikel ist ungefähr 7 Jahre alt und hat praktisch nicht an Relevanz verloren. Es ist jedoch ziemlich schwierig, ihn zu finden, da er nicht in Nikita Popovs Blog enthalten ist, sondern in seinem Artikel über Github veröffentlicht wird. Ich denke, es wird nützlich sein, es der Community auf Russisch zu präsentieren.



In meinem Lieblings- Reddit- Community- Lolphp bin ich auf einen Beitrag gestoßen, in dem die Leute über das Ergebnis des folgenden Codes überrascht sind:



<?php

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

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


Wie Sie sehen können, geben Ausdrücke ($a + $a++)und ($a + $a + $a++)das gleiche Ergebnis, was ziemlich unerwartet ist. Was ist hier los?



Vorrang und Assoziativität des Operators



Viele Leute denken, dass die Reihenfolge, in der ein Ausdruck ausgewertet wird, durch die Priorität und Assoziativität der Operatoren bestimmt wird , aber dies ist nicht der Fall. Priorität und Assoziativität bestimmen nur die Reihenfolge der Gruppierungsoperationen in einem Ausdruck.

Im ersten Ausdruck hat das $c = $a + $a++;Nachinkrementieren von "++" Vorrang vor "+", sodass $ a ++ eine separate Gruppe ist:



$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. Der Bediener @deaktiviert die CV-Optimierung und verschlechtert dadurch die Leistung. Der Bediener ist @grundsätzlich schlecht für die Leistung.


~ nikic



Anmerkung des Übersetzers: Wie oben erwähnt, werden @CV-Optimierungen nur in 5.x deaktiviert. In PHP 7 finden CV-Optimierungen auch dann statt, wenn der Operator zur Fehlerunterdrückung verwendet wird (dies ist jedoch möglicherweise nicht in allen Fällen der Fall). Nikita Popov hat einen interessanten Blog-Beitrag, Static Optimization in PHP 7 , für den Fall, dass jemand tiefer in das Thema Optimierung eintauchen möchte.




All Articles