php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #61188 Assignment changes order of evaluation of binop expression
Submitted: 2012-02-26 17:54 UTC Modified: 2012-02-26 19:43 UTC
From: antickon at gmail dot com Assigned:
Status: Not a bug Package: Variables related
PHP Version: 5.3.10 OS: linux
Private report: No CVE-ID:
 [2012-02-26 17:54 UTC] antickon at gmail dot com
Description:
------------
An assignment expression can change the order of operation for == and != (and 
possibly other binops)

Test script:
---------------
<?php
$a = 3;
var_dump( $a == ( $a = 4 ) );

Expected result:
----------------
bool(false)

evaluation of $a == ( $a = 4 ) should be as follows:
left side of the comparison is evaluated (evaluates to 3)
right side of the comparison is evaluated (4 is assigned to $a, evaluates to 4)
3 == 4 finally evaluates to false

Actual result:
--------------
bool(true)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-02-26 18:16 UTC] rasmus@php.net
-Status: Open +Status: Not a bug
 [2012-02-26 18:16 UTC] rasmus@php.net
You are outsmarting yourself here. Look at your brackets.

$a == ($a=4)  

So we do the bracketed expression first: $a=4 which sets $a to 4 obviously and 
returns the value 4. So what are we left with?

$a == 4

But what is $a at this point? Well, it is 4 of course, because we just set it. 
So we have:

4 == 4

If you can find a language where this expression doesn't return true, regardless 
of the initial value of $a, then you should file a bug against that language.
 [2012-02-26 18:35 UTC] antickon at gmail dot com
I'm afraid you're mistaken. The brackets denote a change in expression binding, 
not evaluation order. If what you are saying is true

<?php
function a(){echo 'a';}
function b(){echo 'b';}
a() == (b());

would output ba since the bracketed expression would be evaluated first. However 
it (correctly) outputs ab.

In fact, the brackets are completely irrelevant. I added them for clarity. 
Consider the equivalent example:

<?php
$a = 3;
var_dump( $a == $a = 3 );
 [2012-02-26 18:38 UTC] rasmus@php.net
Then C/C++/Perl and the other C-like languages are all wrong as well then.

Try this in C:

#include <stdio.h>
int main(char *argv[], int argc) {
	int a=3;
	printf("%d\n",(a==(a=4)));
}

Or this in Perl:

$a=3;
print $a==($a=4);
 [2012-02-26 19:00 UTC] antickon at gmail dot com
What C or perl does is not the issue. The PHP documentation on operator 
precedence states parentheses force precedence, not evaluation order of 
subexpressions. You are saying that arbitrarily changing evaluation order 
depending on the type of subexpression is correct behavior. You have not yet 
provided any rational justification for this behavior, except that C and perl 
also behave this way.
 [2012-02-26 19:04 UTC] rasmus@php.net
I do see your argument, but you are making assumptions about how PHP handles 
sequence points in expressions which is not documented and thus not stricly 
defined.
 [2012-02-26 19:18 UTC] antickon at gmail dot com
I suppose it is up to you to implement undocumented behavior as you see fit, 
however peculiar it is. I'll post a comment on the operator precedence page to 
document it though.

Fyi, I tested this in Javascript and Java and they both evaluate strictly left-
to-right.
 [2012-02-26 19:22 UTC] cataphract@php.net
I think the point here is that we make no guarantee about the order of 
evaluation (or apparent order, as the implementation may just be checking 
whether the same variable is both sides; I haven't checked), 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?

Not that this is particularly relevant, but the only language I tried where the 
behavior is what you expect is Mathematica (a = 3; (a = 4) == a is True and a = 
3; a == (a = 4) is False), but it documents this behavior in 
http://reference.wolfram.com/mathematica/tutorial/TheStandardEvaluationProcedure
.html
 [2012-02-26 19:43 UTC] antickon at gmail dot com
I assumed subexpression evaluation should be strictly left-to-right. But you are 
right, it is actually not guaranteed either way. Thanks for pointing that out. I 
believe it should be guaranteed strictly left-to-right, but that's just my 
opinion. Proper programming practice (PrPrPr (TM)) would be not to compare 
expressions with side-effects anyway.

PS. I put that comment under the page on expressions rather than the one on 
operator precedence
http://www.php.net/manual/en/language.expressions.php
 [2012-09-01 19:01 UTC] avp200681 at gmail dot com
Well, I understand why it works that way in PHP (and in C).
But 
"Can you point to any place on the documentation where it's stated that the first 
operand is evaluated first?"
I've found in PHP documentation: 
"Operators on the same line have equal precedence, in which case associativity decides the order of evaluation."

So, I think it would be good to have a note about this behaviour in PHP manual. Just to make things clear. Because many people think that "associativity decides the order of evaluation" also in the examples like antickon posted.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 16 18:01:53 2014 UTC