Why is $a + ++$a == 2?
PhpMathOperator PrecedencePhp Problem Overview
If I try this:
$a = 0;
echo $a + ++$a, PHP_EOL;
echo $a;
I get this output:
2
1
Demo: http://codepad.org/ncVuJtJu
###Why is that?
I expect to get this as an output:
1
1
###My understanding:
$a = 0; // a === 0
echo $a + ++$a, PHP_EOL; // (0) + (0+1) === 1
echo $a; // a === 1
But why isn't that the output?
Php Solutions
Solution 1 - Php
All the answers explaining why you get 2 and not 1 are actually wrong. According to the PHP documentation, mixing +
and ++
in this manner is undefined behavior, so you could get either 1 or 2. Switching to a different version of PHP may change the result you get, and it would be just as valid.
See example 1, which says:
// mixing ++ and + produces undefined behavior
$a = 1;
echo ++$a + $a++; // may print 4 or 5
Notes:
-
Operator precedence does not determine the order of evaluation. Operator precedence only determines that the expression
$l + ++$l
is parsed as$l + (++$l)
, but doesn't determine if the left or right operand of the+
operator is evaluated first. If the left operand is evaluated first, the result would be 0+1, and if the right operand is evaluated first, the result would be 1+1. -
Operator associativity also does not determine order of evaluation. That the
+
operator has left associativity only determines that$a+$b+$c
is evaluated as($a+$b)+$c
. It does not determine in what order a single operator's operands are evaluated.
Also relevant: On this bug report regarding another expression with undefined results, a PHP developer says: "We make no guarantee about the order of evaluation [...], just as C doesn't. Can you point to any place on the documentation where it's stated that the first operand is evaluated first?"
Solution 2 - Php
A preincrement operator "++" takes place before the rest of the expression it's in evaluates. So it is actually:
echo $l + ++$l; // (1) + (0+1) === 2
Solution 3 - Php
a + b
a = 1
b = ++a
:= 2
Why do you expect something else?
In PHP:
$a = 0;
$c = $a + ++$a;
Operator precedence visualized:
$c = ($a) + (++$a);
Evaluation sequence visualized:
$a = 0; ($a = 0)
$a = 1; (++$a)
$c = $a + $a (1 + 1);
Or written out:
The moment the sum operation is performed, $a
is already 1 because ++$a
has been already evaluated. The ++
operator is evaluated before the +
operator.
For the fun:
$a++ + ++$a
Results in 2, too. However if you compare it as an expression, it's not equal:
$a++ + ++$a == $a + ++$a
Where as
$a++ + ++$a == $a-- + --$a
is "equal".
See Also:
Solution 4 - Php
My Evaluation Order in PHP blog post explain this in detail, but here is the basic idea:
- Operator precedence and associativity have nothing to do with evaluation order.
- PHP does not guarantee an evaluation order. The order can change between PHP versions without notice and can also be different depending on the surrounding code.
- "Normally" PHP will evaluate left-to-right, with the exception of accesses to "simple" variables (like
$a
). Accesses to simple variables will be executed after more complex expressions, regardless in which order the expressions actually occur. - In this particular case it means that
++$a
is run first because it is a complex expression and only then the value of$a
is fetched (it is already 1 at this point). So effectively you are summing1 + 1 = 2
. - The reason that simple variables are fetched after complex expressions is the Compiled Variables (CV) optimization. If you disable this optimization, for example by using the
@
error suppression operator, all expressions are evaluated left-to-right, including simple variable fetches. - In this particular case it means that
@($a + ++$a)
will result in1
, because first$a
is fetched (0 at that time) and incremented only after that.
Solution 5 - Php
++
is the higher precedence operator, so it gets applied first.
So now l = 1.
So 1 + 1 = 2.
Solution 6 - Php
When you do your ++$l (preincrement), it will be done before your addition -> check operator precedence).
So, the value of $l
will be 1
before your addition :
echo $l + ++$l; // $l => 1 because ++$l is done first
So your answer will be 2.
But when you do :
echo $l // you will get your first value which is $l => 1
So your answer will be 1.
Solution 7 - Php
This behaviour can be confirmed by inspecting how PHP compiles your script, for example:
$a = 0;
echo $a + ++$a;
Compiles into the following opcodes, which are then executed:
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
This translates to the following equivalent script:
$a = 0; // ASSIGN
$tmp = ++$a; // PRE_INC
echo $a + $tmp; // ADD, ECHO
Conclusion
By the time $a
is evaluated as the left hand expression of $a + (++$a)
, it has already been incremented, because ++$a
was evaluated first.
Obviously, this behaviour should not be relied upon; in any language for that matter.
Solution 8 - Php
Check the increment operator manual:
http://www.php.net/manual/en/language.operators.increment.php
Or see this codepad: 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;
Outputs:
++ before:2
++ after:1
n:1
m:1
Solution 9 - Php
As you may know we have two increment operator, one is pre-increment and second is post-increment. Pre-increment increase the value of integer before it use in expression, on the other hand post increment increase value of number after it used in expression.
suppose you have variable $a and variable $b as below
$a=0;
$b=++$a gives the value of b=1
while
$b=$a++ gives the value b=0
Solution 10 - Php
The output of your code varies with PHP version as seen here
> Output for 4.3.0 - 5.0.5
> 1
> 1
In the above case the left hand side of +
operator is evaluated first (0, 1, +).
> Output for 5.1.0 - 5.5.0alpha4
> 2
> 1
In the above case the right hand side of +
operator is evaluated first (1, 1, +).
This is in accordance with interjay's answer that in PHP there is no guarantee about the order of evaluation of sub-expresions. The assumption that the output could be 1, 1
is correct, so are that answers that claim that the output could be 1, 2
.
Solution 11 - Php
First obvious part is that ++
have higher priority than +
.
Second part is that php engine doesn't store value from first operand into another anonymous variable. So $l + ++$l
is not an qeuivalent for
$a = $l;
$b = ++$l;
return $a + $b;
Solution 12 - Php
As mentioned before there is a difference in x++ and ++x. You can interpret it in the way that
x++;
increments after the semicolon
and
++x;
increments on evaluation of the expression
So it seems that your expression is evaluated from right to left
echo $l + ++$l;
2. Get $l: $l = 0 3. Apply ++: ++$l = 1
- Get $l: $l = 1
- Apply +: $l + $l = 1 + 1 = 2
Solution 13 - Php
All statements are executed from right to left. So the value is first incremented than the value of your variable is = 1 so 1+1=2