9

In the PHP manual, operator precedence section, there is this example:

// mixing ++ and + produces undefined behavior
$a = 1;
echo ++$a + $a++; // may print 4 or 5

I understand the behavior is undefined because of the following reason:

Since x + y = y + x the interpreter is free to evaluate x and y for addition in any order in order to optimize speed and/or memory. I concluded this after looking at the C code example in this article.

My question is that the output of the above mentioned PHP code should be 4 no matter which way the expression and sub-expressions are evaluated:

  • op1 = ++$a => $a = 2, op1 = 2; op2 = $a++ => op2 = 2, $a = 3; 2 + 2 = 4
  • op1 = $a++ => op1 = 1, $a = 2; op2 = ++$a => op2 = 3, $a = 3; 1 + 3 = 4

Where does the 5 come from? Or should I learn more about how the operators work?

Edit:

I have been staring at Incrementing/Decrementing Operators section but still could not figure out why 5.

++$a: Pre-increment -- Increments $a by one, then returns $a.
$a++: Post-increment -- Returns $a, then increments $a by one.

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
Salman A
  • 262,204
  • 82
  • 430
  • 521
  • Did you really get 5 printed while running this code? – Ranty Jan 02 '13 at 07:24
  • No. I always got 4 with a few versions of PHP. It is the word _may_, it means I could run this code a million times getting the reesult 4 but there is no _guarantee_. – Salman A Jan 02 '13 at 07:27
  • @H2CO3: I am more interested in knowing _why 5_. – Salman A Jan 02 '13 at 07:28
  • http://stackoverflow.com/q/9709818/1607098 – Touki Jan 02 '13 at 07:37
  • Bear in mind that a compiler/interpreter may well choose to do someting in a different way depending on circumstances - are there registers available, can we do something clever because of how it's used next [e.g. staying with the value calculated in a register] – Mats Petersson Jan 02 '13 at 08:35
  • This question has nothing to do with C. Removing that tag. – Alex Reynolds Jan 02 '13 at 08:36

3 Answers3

5
a = 1;
++ (preincrement) gives a = 2 (higher precedence than +, and LR higher precedence than postincrement)
++ (postincrement) gives a = 3 (higher precedence than +)
+ (add) gives 2 + 3 = 5

$a is initially set to 1. The ++$a then preincrements $a before using it in the formula, setting it to 2, and pushing that value onto the lexer stack. The $++ is then executed, because incrementor has a higher precedence than +, and that value is also pushed that result onto the lexer stack; and the addition that then takes place adds the lexer stack's 2 result to the lexer stack's 3 result giving a result of 5, which is then echoed. The value of $a once the line has executed is 3.

OR

a = 1;
++ (preincrement) gives a = 2 (higher precedence than +, and LR higher precedence than postincrement)
+ (add) gives 2 + 2 = 4 (the value that is echoed)
++ (postincrement) gives a = 3 (incremented __after__ the variable is echoed)

$a is initially set to 1. When the formula is parses, the ++$a preincrements $a, setting it to 2 before using it in the formula (pushing the result to the lexer stack). The result from the lexer stack and the current value of $a are then added together giving 4; and this value is echoed. Finally, $a is postincremented, leaving a value of 3 in $a.

Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • 2
    I've edited my question. I had thought of this too but later realized that post increment will return the current value (i.e. 2), _then_ increment a. – Salman A Jan 02 '13 at 07:37
1

Yes it will give you 5 because the right side operator works first by its priority/precendence and after that the sum(+) operator will work. So first increment makes it to 2 and second makes it to 3 and after that both will sum and outputs you the result as 5

$result = ++$a + $a++;

++$a outputs as 2

$a++ outputs as 2 3 only but internally it wll be incremented.

finally sum will happens as 2+3 = 5

Shoe
  • 74,840
  • 36
  • 166
  • 272
Vinoth Babu
  • 6,724
  • 10
  • 36
  • 55
  • 2
    "Yes it will give you 5" - rather "Yes it may also give you 5". –  Jan 02 '13 at 07:30
  • Even if $a is 3 after $a++ is evaluated, the expression $a++ still evaluates to 2, so the sum is 2+2. – fgb Jan 02 '13 at 08:16
0

Mark, I believe you are wrong!

Post-increment: Returns $a, then increments $a by one. (from documentation)

So there is no way to get $a value of 3 in sum operation.

TomTom
  • 1,865
  • 1
  • 13
  • 14
  • The point is that the result is unpredictable: OP was asking how it was possible to get a result of 5, not whether it did give a result of 5 – Mark Baker Jan 02 '13 at 09:12
  • But then an explanation: "++$a gives 0 and $a++ gives 5, so 0 + 5 = 5" would give same effort. I mean, both are against documentation. – TomTom Jan 02 '13 at 11:34