Оценка неинтуитивного выражения с инкрементацией
Для следующего кода
<?php
$a=1; $b=$a++; var_dump($b);
$a=1; $b=$a+$a++; var_dump($b);
$a=1; $b=$a+$a+$a++; var_dump($b);
$a=1; $b=$a+$a+$a+$a++; var_dump($b);
$a=1; $b=$a+$a+$a+$a+$a++; var_dump($b);
Я получил этот результат:
int(1)
int(3)
int(3)
int(4)
int(5)
Я ожидал 1,2,3,4,5, а не 1,3,3,4,5. Почему после $a=1; $b=$a+$a++;
получаем $b=3
?
PHP 7.1.5-1 + deb.sury.org ~ xenial + 1 (cli) (построено: 11 мая 2017 14:07:52) (NTS)
Ответы
Ответ 1
$a=1; $b=$a+$a++; var_dump($b); // int(3)
Вы предположили, что приведенное выше выражение оценивается слева направо следующим образом (временные переменные $u
и $v
вводятся в объяснении для ясности):
$a = 1;
$u = $a; // ($a) the LHS operand of `+`
$v = $a; // \ ($a++) the RHS operand of `+`
$a ++; // /
$b = $u + $v; // 2 (1+1)
Но нет гарантии, что подвыражения будут оцениваться в указанном порядке. На странице документации PHP-операторы говорится (акцент мой):
Приоритет операторов и ассоциативность определяют только то, как сгруппированы выражения, они не определяют порядок оценки. В PHP нет (в общем случае) указать, в каком порядке оценивается выражение, и следует избегать кода, который предполагает определенный порядок оценки, потому что поведение может изменяться между версиями PHP или в зависимости от окружающий код.
Только случайно значения, вычисленные PHP для других выражений, соответствуют значениям, которые вы предположили. Их значения могут отличаться, если код выполняется с использованием другой версии интерпретатора PHP.
Ответ 2
В PHP нет (в общем случае) указать, в каком порядке оценивается выражение, а код, который предполагает определенный порядок оценки, следует избегать [..]
http://php.net/manual/en/language.operators.precedence.php
Причина, по которой вы получаете разные результаты, заключается в том, что иногда сначала оцениваются правый, а иногда и левый операнд. PHP не дает никаких гарантий относительно порядка операций, поэтому нет правильного ответа, и это прямо относится к категории undefined.
Ответ 3
Согласно руководство по PHP
Приоритет и ассоциативность операторов определяют только то, как выражения сгруппированы, они не определяют порядок оценки. PHP не (в общем случае) указать в каком порядке выражение оценки и кода, который предполагает определенный порядок оценки, должен следует избегать, поскольку поведение может изменяться между версиями PHP или в зависимости от окружающего кода.
<?php
$a = 1;
echo $a + $a++; // may print either 2 or 3
$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
?>
Странно то, что я ожидал, что другие строки, такие как $b=$a+$a+$a++;
, будут следовать одному и тому же шаблону, но это не так.