65

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?

2
  • 23
    Whatever you intended $l + ++$l to mean, I guarantee that there's a more straightforward way to express that intent. Commented Mar 15, 2012 at 7:10
  • 1
    as a side note: this is an example of question that Andi Gutmans sometimes use in conference. This is the expected behaviour in php as stated before by other users as ++$l is evaluated before the rest of the expression. Commented Mar 21, 2012 at 9:42

13 Answers 13

115

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:

  1. 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.

  2. 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?"

Sign up to request clarification or add additional context in comments.

10 Comments

Yea, it's because the expression is evaluated from right to left in the parser. But as long as that is not specified the behavior of the expression is not specified and should be avoided.
How does the "assignments are parsed in a right to left order" rule of PHP expressions does not shed some light into this? Won't it remove the undefined behaviour?
@hakre: That rule just says that assignment is right-associative, i.e. $a=$b=$c is parsed as $a=($b=$c). It is only relevant when you have multiple assignment operators in an expression.
@interjay: But for the expression asked about, the left part is not involved in any incrementation. As the right part is triggered first because of operator precedence, it's not undefined. Edit: Well actually you can't say, right.
@hakre: The right part is not necessarily evaluated first. Operator precedence only determines where to add the parentheses here, i.e. $l + ++$l --> $l + (++$l). But it does not determine whether the left or right side of the + operator is evaluated first.
|
66

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 

19 Comments

To add to this: Compare against echo $l + $l++;, which outputs 1 as the OP was expecting.
Side note; is that actually documented for PHP? I can't find anything about its evaluation order vs. the rest of the expression.
@JoachimIsaksson Yes, it is documented as undefined behaviour. @RyanP No, there're languages with defined behaviour in such cases, e.g. Java.
@Corbin Operator precedence does not really explain the evaluation order, since postfix and prefix ++ both have the same precedence but aren't evaluated in the same order.
|
24
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:

6 Comments

@hakre you need to explain this, your answer doesn't make sense.
Yeah, a = 1 because when b is evaluated, a is 1 and not 0. Was not really clear for everybody, I edited the answer. And for the fun, I added some bonus expressions at the end.
@hakre: I added another, very similar question
@hakre OT: Your print_r converted is .. broken. Care to fix your link ?
@Martin.: It was based on codepad viper but codepad viper changed. You can find the source here: gist.github.com/1102761
|
7

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 summing 1 + 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 in 1, because first $a is fetched (0 at that time) and incremented only after that.

1 Comment

That's not a blog post, that's a gist :(
6

++ is the higher precedence operator, so it gets applied first.

So now l = 1.

So 1 + 1 = 2.

6 Comments

Actually both prefix and postfix ++ are the same precedence, so precedence shouldn't have anything to do with evaluation order.
@JoachimIsaksson I believe he was referring to the precedence of ++ over +.
Yep, in the snippet above we only have prefix not postfix.
Seriously, what? the word precedence doesn't give it away?
Precedence only determines grouping. Evaluation order is independent.
|
3

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.

Comments

2

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.

Comments

1

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 

Comments

1

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

Comments

1

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.

Comments

0

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; 

2 Comments

Sorry but operator priority has nothing to do with this. All answers mentioning operator precedence are incorrect.
So just because of I mentioned operator precedence, my answer become incorrect. Ha-ha, funny.
0

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; 
  1. Get $l: $l = 0
  2. Apply ++: ++$l = 1
  3. Get $l: $l = 1
  4. Apply +: $l + $l = 1 + 1 = 2

Comments

-2

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.