This question already has answers here:
Why is $a + ++$a == 2?
(13 answers)
Closed last year.
As i know, preincrement is calculated before all other operations, postincrement is calculated after all operations.
In php docs it is said that increment (as i understand exactly pre-increment) has very high precedence. Post-increment should have very low precedence, in fact, lowest one.
+ operator precedence is MUCH MORE lower then ++ one (acording to docs).
So, now the question: In php docs there is an example, that shows that preincrement and postincrement in one expression can vary:
// mixing ++ and + produces undefined behavior
$a = 1;
echo ++$a + $a++; // may print 4 or 5
Why? WTF? I see following scenario an it is very clear:
Preincrement $a
Calculate sum for $a and $a
Post increment $a
I can't understand why it is unpredictable.
PHP documentation regarding this subject (and also this example) could be found there:
http://www.php.net/manual/en/language.operators.precedence.php
It would always produce 4 because the last $a is using Post-increment for it to produce 5 then use Pre-increment like the first $a
$a = 1;
echo ++ $a + $a++; // 4
And
$a = 1;
echo ++ $a + ++ $a; // 5
Incrementing/Decrementing Operators
Related
This question already has answers here:
Is there a PHP function for swapping the values of two variables?
(20 answers)
Closed 9 years ago.
I want to share 1 question which is asked most of the time in interviews and I wasn't able to e answer that question, but finally I found the answer:
How to Swap 2 variable value without using 3rd variable??
This method will work for any variable type:
$a = 5;
$b = 6;
list($a, $b) = array($b, $a);
print $a . ',' . $b;
Output:
6,5
Another simple way (which only works for numbers, not strings/arrays/etc) is
$a = $a + $b; // 5 + 6 = 11
$b = $a - $b; // 11 - 6 = 5
$a = $a - $b; // 11 - 5 = 6
print $a . ',' . $b;
Output:
6,5
Surely you want the XOR swap algorithm ? At least for numeric variables.
Conventional swapping requires the use of a temporary storage
variable. Using the XOR swap algorithm, however, no temporary storage
is needed. The algorithm is as follows:
X := X XOR Y
Y := X XOR Y
X := X XOR Y
Although I've never seen it used in real scenarios (beyond assembler work)
This question already has answers here:
Why is $a + ++$a == 2?
(13 answers)
Closed 10 years ago.
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.
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.
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
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.
I have a situation here with post fix and prefix operator.Take a look at below code snippet. I know some operator precedence exist. but i need a clear explanation regarding this.
<?php
$a=0;
echo $a++ + ++$a; //this will result 2 that is ok
$b=0;
echo $b++ - ++$b; //this should result 0 isn't it? but am getting -2!
?>
Update : The accepted answer describes undefined behavior
That always happens if you make use of undefined behaviour. And what you do is undefined behaviour. So don't try to get an explanation that follows a deterministic logic as undefined is the opposite of that.
The PHP manual states:
// mixing ++ and + produces undefined behavior
$a = 1;
echo ++$a + $a++; // may print 4 or 5
You extended your question in a comment:
echo $c=($b++) - (++$b); the result of this statement also getting -2. What you meant by undefined behavior?
$b = 0 and it shall:
$c=($b++) - (++$b); | $b is 0 - process first brackets
$c= 0 - (++$b); | $b is 1 - process second bracktes inner operator
$c= 0 - ($b); | $b is 2 - process second brackets
$c= 0 - 2; | calculate
$c= -2;
This is obviously how it results for your code when you execute it. It is not defined that this will be always calculated that way, hence undefined. For example if the second bracket is processed first, you'll get a different result.
Due to Incrementing/Decrementing Operators (PHP doc)
<?php
$a=0;
echo $a++ + ++$a; // 0 + 2 = 2
$b=0;
echo $b++ - ++$b; // 0 - 2 = -2
?>
$a++ returns 0 and increments $a by 1 ($a == 1);
++$a increments $a by 1 ($a == 2) and returns 2
The results are perfectly fine:
$a++ prints the value and increments it immediatly
++$a increments before output
so in the first case this would be like:
$a=0
output 0
increment $a by 1: $a=1
increment again (before output): $a=2
output 2
0+2 = 2
in the second case:
$b=0
output 0
increment $b by 1: $b=1
increment again (before output): $b=2
output 2
0 - 2 = -2
It justz does what it says.
Regards,
STEFAN
The php manual claims that:
$a = 1;
echo ++$a + $a++;
is ambiguous under its grammar, but it seems extremely clear to me. ++$a and $a++ evaluate first, from left to right, so ++$a increments and then returns 2, and $a++ returns 2 and then increments. The sum of 2 + 2 is 4, so it would echo 4. However, The PHP Manual says very clearly that it may print 4 or 5.
Does the php spec not specify that operations will be performed from left to right?
Even if it doesn't enforce that operations will be performed from left to right, in this case, wouldn't it return 4 regardless?
Edit: I reread the page, and it stated that it is determined by each specific operator. + has lowest precedence, and evaluates from left to right, so it seems like my earlier assumption was correct. I still do not understand.
++$a let $a be 2, and return 2,
$a++ increment $a again, so $a is 3 now, but it return 2.
In the same PHP version, the result is always same. But it may produce different result if PHP version changed. It depends on ++$a and $a++, which one is evaluated first. If $a++ is evaluated first, the result will be 5, otherwise the result will be 4.
Please note that this is just my humble opinion.
I think the idea beneath this result is that none of the aperands has precedence when there's a single operator and that in an operation a variable is kept as a reference instead of being replaced by its result during all the calculation until the last one (plus, in this example). So when it goes from l-r:
$a = 1;
++$a + $a++
operand 1 --> ++$a ==> $a = ++1 = 2
result (where $a = 2) --> 2 + (2++) = 4
whereas otherwise:
$a = 1;
++$a + $a++
operand 2 --> $a++ ==> $a = 1
// new operation on the left side
// so the value gets incremented ==> $a = 2
result (where $a = 2) --> (++2) + 2 = 5
I'm not sure about this, though.
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?
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?"
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
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:
Order of evaluation in PHP (Sep 2013; by NikiC) (via)
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.
++ is the higher precedence operator, so it gets applied first.
So now l = 1.
So 1 + 1 = 2.
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.
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.
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
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
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.
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;
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;
Get $l: $l = 0
Apply ++: ++$l = 1
Get $l: $l = 1
Apply +: $l + $l = 1 + 1 = 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