PHPでの評価順序

翻訳者のメモ。Nikita Popovは、PHP言語の開発に多大な貢献をしてきました。彼はPHPエンジンの内部をよく理解しており、この記事では、式の評価の順序の観点からPHPの機能のいくつかを説明していますが、おそらくどこにも特に見られません。この記事は約7年前のものであり、実質的に関連性を失っていませんが、Nikita Popovのブログにはないため、見つけるのはかなり困難ですが、githubの彼の要点に掲載されています。ロシア語でコミュニティに提示することは有益だと思います。



私のお気に入りのredditコミュニティlolphpで、次のコードの結果に人々が驚いている投稿に出くわしました。



<?php

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

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


ご覧のとおり、式($a + $a++)($a + $a + $a++)同じ結果が得られますが、これはまったく予想外のことです。何が起きてる?



演算子の優先順位と関連性



多くの人は、式が評価される順序は演算子の優先順位と関連性によって決定されると考えていますが、そうではありません。優先度と関連性は、操作が式にグループ化される順序のみを決定します。

最初の式では、$c = $a + $a++;ポストインクリメントの「++」が「+」よりも優先されるため、$ a ++は別のグループです。



$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. オペレーター@はCV最適化を無効にし、結果としてパフォーマンスを低下させます。原則として、オペレーターは@パフォーマンスに悪影響を及ぼします。


nikic



翻訳者のメモ:前述のように、@CV最適化は5.xでのみ無効になります。PHP7では、エラー抑制演算子が使用されている場合でもCV最適化が行われます(ただし、すべての場合に発生するとは限りません)。Nikita Popovには、最適化のトピックをさらに深く掘り下げたい場合に備えて、興味深いブログ投稿「PHP7の静的最適化」があります。




All Articles