Почему $a + ++ $a == 2?
Если я попробую это:
$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
Но почему это не так?
Ответы
Ответ 1
Все ответы, объясняющие, почему вы получаете 2, а не 1, на самом деле ошибаются. Согласно документации PHP, смешение +
и ++
таким образом - это поведение undefined, поэтому вы можете получить либо 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
. Он не определяет, в каком порядке оцениваются операнды одного оператора.
Также уместно: в этом отчете об ошибке относительно другого выражения с результатами undefined разработчик PHP говорит:" Мы не гарантируем порядок оценки [...], так же, как и нет. Можете ли вы указать на любое место в документации, где указано, что первый операнд сначала оценивается?
Ответ 2
Оператор preincrement "++" имеет место перед остальной частью выражения, которое он оценивает. Так оно и есть на самом деле:
echo $l + ++$l; // (1) + (0+1) === 2
Ответ 3
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
является "равным".
См. также:
Ответ 4
My Оценка в PHP в блоге объясните это подробно, но вот основная идея:
- приоритет оператора и ассоциативность не имеют ничего общего с порядком оценки.
- PHP не гарантирует порядок оценки. Заказ может изменяться между версиями PHP без уведомления и может также отличаться в зависимости от окружающего кода.
- "Обычно" PHP будет оценивать слева направо, за исключением доступа к "простым" переменным (например,
$a
). Доступ к простым переменным будет выполняться после более сложных выражений, независимо от того, в каком порядке действительно существуют выражения.
- В этом конкретном случае это означает, что
++$a
выполняется сначала, потому что это сложное выражение, и только тогда выбирается значение $a
(оно уже 1 в этой точке). Таким образом, вы суммируете 1 + 1 = 2
.
- Причина, по которой простые переменные извлекаются после сложных выражений, это оптимизация скомпилированных переменных (CV). Если вы отключите эту оптимизацию, например, используя оператор подавления ошибок
@
, все выражения оцениваются слева направо, включая простые выборки переменных.
- В этом конкретном случае это означает, что
@($a + ++$a)
приведет к 1
, потому что сначала $a
извлекается (0 в это время) и увеличивается только после этого.
Ответ 5
++
- это оператор с более высоким приоритетом, поэтому он сначала применяется.
Итак, теперь l = 1.
So 1 + 1 = 2.
Ответ 6
Когда вы выполняете свой ++ $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.
Ответ 7
Такое поведение можно подтвердить, проверив, как PHP компилирует ваш script, например:
$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
Это означает следующий эквивалент script:
$a = 0; // ASSIGN
$tmp = ++$a; // PRE_INC
echo $a + $tmp; // ADD, ECHO
Заключение
К моменту $a
оценивается как левое выражение $a + (++$a)
, оно уже было увеличено, потому что сначала оценивалось ++$a
.
Очевидно, что это поведение должно не полагаться на; на любом языке.
Ответ 8
Проверьте инструкцию оператора инкремента:
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
Ответ 9
Как вы знаете, у нас есть два оператора инкремента, один - предварительный приращение, а второй - пост-инкремент. Предварительное приращение увеличивает значение целого числа до его использования в выражении, с другой стороны, увеличение пошагового увеличения числа после использования в выражении.
предположим, что у вас есть переменная $a и переменная $b, как показано ниже
$а = 0;
$b = ++ $a дает значение b = 1
а
$b = $a ++ дает значение b = 0
Ответ 10
Вывод вашего кода зависит от версии PHP как показано здесь
Выход для 4.3.0 - 5.0.5
1
1
В приведенном выше случае сначала обрабатывается левая сторона оператора +
(0, 1, +).
Выход для 5.1.0 - 5.5.0alpha4
2
1
В приведенном выше случае правая часть оператора +
оценивается сначала (1, 1, +).
Это соответствует interjay answer, что в PHP нет гарантии о порядке оценки суб-выражений. Предположение о том, что вывод может быть 1, 1
, является правильным, так же как и те ответы, которые утверждают, что вывод может быть 1, 2
.
Ответ 11
Первая очевидная часть состоит в том, что ++
имеют более высокий приоритет, чем +
.
Вторая часть - это то, что php-движок не сохраняет значение из первого операнда в другую анонимную переменную. Итак, $l + ++$l
не является qeuivalent для
$a = $l;
$b = ++$l;
return $a + $b;
Ответ 12
Как упоминалось ранее, существует разница в x ++ и ++ x. Вы можете интерпретировать его так, как
x++;
увеличивается после точки с запятой
и
++x;
увеличивается при оценке выражения
Итак, кажется, что ваше выражение оценивается справа налево
echo $l + ++$l;
- Получить $l: $l = 0
- Применить ++: ++ $l = 1
- Получить $l: $l = 1
- Применить +: $l + $l = 1 + 1 = 2
Ответ 13
Все операторы выполняются справа налево.
Таким образом, значение сначала увеличивается, чем значение вашей переменной = 1, поэтому 1 + 1 = 2