Почему $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.

Очевидно, что это поведение должно не полагаться на; на любом языке.

Ответ 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