Если я попробую:
$a = 0; echo $a + ++$a, PHP_EOL; echo $a;
Я получаю этот вывод:
2 1
Демо: http://codepad.org/ncVuJtJu
Я ожидаю получить это как результат:
1 1
$a = 0; // a === 0 echo $a + ++$a, PHP_EOL; // (0) + (0+1) === 1 echo $a; // a === 1
Но почему это не так?
Все ответы, объясняющие, почему вы получаете 2, а не 1, действительно ошибаются. Согласно документации PHP, смешение +
и ++
таким образом – неопределенное поведение, поэтому вы можете получить либо 1, либо 2. Переход на другую версию PHP может изменить полученный результат, и это будет так же справедливо.
См. Пример 1 , в котором говорится:
// mixing ++ and + produces undefined behavior $a = 1; echo ++$a + $a++; // may print 4 or 5
Заметки:
Приоритет оператора не определяет порядок оценки. Приоритет оператора только определяет, что выражение $l + ++$l
анализируется как $l + (++$l)
, но не определяет, будет ли первый или правый операнд оператора +
оцениваться первым. Если первый операнд сначала оценивается, результат будет равен 0 + 1, и если сначала будет оценен правый операнд, результат будет равен 1 + 1.
Ассоциативность операторов также не определяет порядок оценки. То, что оператор +
оставил ассоциативность, только определяет, что $a+$b+$c
оценивается как ($a+$b)+$c
. Он не определяет, в каком порядке оцениваются операнды одного оператора.
Также уместно: в этом отчете об ошибке, относящемся к другому выражению с неопределенными результатами, разработчик PHP говорит: «Мы не гарантируем порядок оценки […], так же, как и нет. Можете ли вы указать на любое место на где указано, что первый операнд оценивается первым? "
Оператор preincrement «++» имеет место перед остальной частью выражения, которое он оценивает. Так это на самом деле:
echo $l + ++$l; // (1) + (0+1) === 2
a + b a = 1 b = ++a := 2
Почему вы ожидаете чего-то еще?
В PHP:
$a = 0; $c = $a + ++$a;
Предшествующий приоритет оператора :
$c = ($a) + (++$a);
Последовательность оценки визуализируется:
$a = 0; ($a = 0) $a = 1; (++$a) $c = $a + $a (1 + 1);
Или выписано:
В тот момент, когда выполняется операция суммирования, $a
уже равен 1, потому что ++$a
уже был оценен. Оператор ++
вычисляется перед оператором +
.
Для удовольствия:
$a++ + ++$a
Результаты в 2 тоже. Однако, если вы сравниваете его как выражение, оно не равно:
$a++ + ++$a == $a + ++$a
В то время как
$a++ + ++$a == $a-- + --$a
равно".
Смотрите также:
Мой порядок оценки в блоге в блоге PHP объясняет это подробно, но вот основная идея:
$a
). Доступ к простым переменным будет выполняться после более сложных выражений, независимо от того, в каком порядке фактически выполняются выражения. ++$a
выполняется сначала, потому что это сложное выражение, и только тогда выдается значение $a
(оно уже 1 в этой точке). Таким образом, вы суммируете 1 + 1 = 2
. @
ошибки, все выражения оцениваются слева направо, включая простые выборки переменных. @($a + ++$a)
приведет к 1
, потому что сначала $a
выбирается (0 в это время) и увеличивается только после этого. ++
– это оператор с более высоким приоритетом, поэтому он сначала применяется.
Итак, теперь l = 1.
Итак, 1 + 1 = 2.
Когда вы выполняете свой ++ $ l (preincrement), это будет сделано до вашего добавления -> проверить приоритет оператора ).
Таким образом, значение $l
будет равно 1
до вашего добавления:
echo $l + ++$l; // $l => 1 because ++$l is done first
Таким образом, ваш ответ будет 2.
Но когда вы это сделаете:
echo $l // you will get your first value which is $l => 1
Таким образом, ваш ответ будет 1.
Такое поведение можно подтвердить, проверив, как PHP компилирует ваш скрипт, например:
$a = 0; echo $a + ++$a;
Компилирует следующие коды операций, которые затем выполняются:
compiled vars: !0 = $a line # * op fetch ext return operands --------------------------------------------------------------------------------- 1 0 > ASSIGN !0, 0 1 PRE_INC $1 !0 2 ADD ~2 !0, $1 3 ECHO ~2 4 > RETURN null
Это приводит к следующему эквивалентному сценарию:
$a = 0; // ASSIGN $tmp = ++$a; // PRE_INC echo $a + $tmp; // ADD, ECHO
Вывод
К тому времени, когда $a
оценивается как левое выражение $a + (++$a)
, оно уже было увеличено, потому что сначала оценивался ++$a
.
Очевидно, на это поведение нельзя полагаться ; на любом языке.
Проверьте руководство оператора инкремента:
http://www.php.net/manual/en/language.operators.increment.php
Или посмотрите этот код: http://codepad.org/Y3CnhiLx
<?php $n = 0; $m = 0; echo '++ before:'; echo $n+ ++$n; echo PHP_EOL; echo '++ after:'; echo $m+ $m++; echo PHP_EOL; echo 'n:'.$n; echo PHP_EOL; echo 'm:'.$m;
Выходы:
++ before:2 ++ after:1 n:1 m:1
Как вы, возможно, знаете, у нас есть два оператора инкремента, один – предварительный приращение, а второй – пост-инкремент. Предварительное приращение увеличивает значение целого числа до его использования в выражении, с другой стороны, приращение post увеличивает значение числа после использования в выражении.
предположим, что у вас есть переменная $ a и переменная $ b, как показано ниже
$ А = 0;
$ b = ++ $ a дает значение b = 1
в то время как
$ b = $ a ++ дает значение b = 0
Вывод вашего кода зависит от версии PHP, как показано здесь.
Выход для 4.3.0 – 5.0.5
1
1
В приведенном выше случае сначала обрабатывается левая часть оператора +
(0, 1, +).
Выход для 5.1.0 – 5.5.0alpha4
2
1
В приведенном выше случае правая часть оператора +
вычисляется сначала (1, 1, +).
Это соответствует ответу interjay, что в PHP нет гарантии о порядке оценки суб-экспресии. Предположение о том, что вывод может быть 1, 1
является правильным, так и ответы, которые утверждают, что выход может быть 1, 2
.
Первая очевидная часть заключается в том, что ++
имеет более высокий приоритет, чем +
.
Вторая часть заключается в том, что php-движок не сохраняет значение из первого операнда в другую анонимную переменную. Таким образом, $l + ++$l
не является qeuivalent для
$a = $l; $b = ++$l; return $a + $b;
Как упоминалось ранее, существует разница в x ++ и ++ x. Вы можете интерпретировать это так, как это
x++;
приращения после точки с запятой
а также
++x;
приращения при оценке выражения
Таким образом, кажется, что ваше выражение оценивается справа налево
echo $l + ++$l;
Все утверждения выполняются справа налево. Таким образом, значение сначала увеличивается, чем значение вашей переменной = 1, поэтому 1 + 1 = 2