sneskid Posted March 8, 2007 Share Posted March 8, 2007 (v5.1.4) function xyz(&$v){$v++;return $v;} $a = array(); $b=0; $a[$b] = $b++; // [1]=>int(0) $a[$b] = ++$b; // [2]=>int(2) $a[$b] = xyz($b); // [3]=>int(3) $a[$c=$b] = xyz($b); // [3]=>int(4) $c negates the bug|feature var_dump($a); When $b is altered on the right side, it alters the expected assign-to index of $a on the left side. This shows that the left side evaluation can be effected after the right side evaluation. In other languages, for example Javascript, $a[$b] would have first been evaluated&locked as $a[0]. Quote Link to comment Share on other sites More sharing options...
obsidian Posted March 8, 2007 Share Posted March 8, 2007 OK, now you've got me testing, and I'm really confuzzled ... Compare the following and tell me which logically would come first: <?php // Test one $a = array(); $b = 0; $a[$b++] = $b; // Outcome: "[0] => int(1)" // Compare to test two $a = array(); $b = 0; $a[$b] = $b++; // Outcome: "[1] => int(0)" ?> My guess was that the first result would be exactly what it is since the key would increment the variable before it is used on the right side of the assignment. However, the second test still has me confused. I thought it would be [0] => int(0), but $b would be incremented to '1' after the assignment. I'm very interested to get other people's input on this. It does seem inconsistent to me as well. Quote Link to comment Share on other sites More sharing options...
rofl90 Posted March 8, 2007 Share Posted March 8, 2007 LOL Obsidian well dne... wow that was a basic thing. workitout jeeeeez. Quote Link to comment Share on other sites More sharing options...
trq Posted March 8, 2007 Share Posted March 8, 2007 php -v 4.3.10 I got exactly as you would expect. <?php $a = array(); $b = 0; $a[$b++] = $b; print_r($a)."\n"; echo $b."\n\n"; $a = array(); $b = 0; $a[$b] = $b++; print_r($a)."\n"; echo $b."\n\n"; ?> Produced.... Array ( [0] => 1 ) 1 Array ( [0] => 0 ) 1 Quote Link to comment Share on other sites More sharing options...
btherl Posted March 8, 2007 Share Posted March 8, 2007 Most languages leave such obscure questions undefined. Just don't do it Your code may work for this version of php, but there's no guarantees it will work next version. The same goes for function calls like f($b++, $b++); Quote Link to comment Share on other sites More sharing options...
obsidian Posted March 8, 2007 Share Posted March 8, 2007 php -v 4.3.10 Hmm... interesting. I'm running 5.2.1. I tested on 4.3.10, and it works just as you said: like you expect it to. Very interesting. Quote Link to comment Share on other sites More sharing options...
trq Posted March 8, 2007 Share Posted March 8, 2007 Just don't do it Hahaha. Thats probably the best advice Ive heard all week. Quote Link to comment Share on other sites More sharing options...
btherl Posted March 8, 2007 Share Posted March 8, 2007 Here's another one for you.. $i = 7; print ($i-- * $i++) . "\n"; $i = 7; print ($i++ * $i--) . "\n"; Here in php 4.3.10 and 5.1.4 I get this output: 42 56 And here's another oddity I found while wondering why my sorting wasn't working properly if ("2" < "10") print "2 < 10\n"; if ("10" < "10a") print "10 < 10a\n"; if ("10a" < "2") print "10a < 2\n"; This shows that a < b < c < a, which gives a loop in the ordering Quote Link to comment Share on other sites More sharing options...
obsidian Posted March 8, 2007 Share Posted March 8, 2007 Here's another one for you.. $i = 7; print ($i-- * $i++) . "\n"; $i = 7; print ($i++ * $i--) . "\n"; Here in php 4.3.10 and 5.1.4 I get this output: 42 56 And here's another oddity I found while wondering why my sorting wasn't working properly if ("2" < "10") print "2 < 10\n"; if ("10" < "10a") print "10 < 10a\n"; if ("10a" < "2") print "10a < 2\n"; This shows that a < b < c < a, which gives a loop in the ordering Those don't necessarily strike me as odd. The first one, especially: if you get 42 and 56, that's exactly how you would expect those increment and decrement operators to work. Remember that when the inc/dec operators come after the variable that the value is used first and then the operation is carried out, so your first example would be figured as follows ($i-- * $i++): $i returns 7 to the equation then decrements itself leaving us with 7 * __. Then, $i returns 6 to the second value and increments itself afterwards giving us 7 * 6 and leaving $i with a value of 7 once again. The reverse is true of the second line giving you 7 * 8 and $i with the value of 7. So, you should get 42 and 56 as your answers. With the other, your comparisons will be implicitly converted to integer comparison when your strings contain only numbers. When they contain alpha characters as well, they will have a string comparison. I'm not sure if that's exactly the best way to state it, but it makes sense that it would come out the way you're showing. Quote Link to comment Share on other sites More sharing options...
btherl Posted March 8, 2007 Share Posted March 8, 2007 But who said expressions should be evaluated left to right? And who specified when the pre and post increment should be done? These things are left unspecified in PHP, so the result could be anything. The possibilities are: 6*6 (decrement, take left value, take right value, increment) 6*7 (decrement, take left value, increment, take right value) 7*7 (take left value, take right value, decrement, increment) 7*8 (take left value, increment, take right value, decrement) All are quite valid way of interpreting the expression. Regarding the sorting, yes it does have logic behind it, it's just not the logic you might expect Here's the details (I made a journal post about it a while back) "2" < "10" - integer comparison "10" < "10a" - string comparison. Longer string wins. "10a" < "2" - string comparison. "2" wins because only the first characters are compared in this case. Quote Link to comment Share on other sites More sharing options...
obsidian Posted March 8, 2007 Share Posted March 8, 2007 But who said expressions should be evaluated left to right? And who specified when the pre and post increment should be done? These things are left unspecified in PHP, so the result could be anything. Not true at all... Read the manual about increment and decrement operators. There are "pre" and "post" increment and decrement operators that are very clearly documented: not to mention this is something that is cross-language accurate, so it goes beyond simply PHP to a programming theory now. If you use the post increment operator, as you have, you will see on the page I cited that the value of the variable is very clearly used before the increment takes place, and the variable is immediately incremented/decremented as soon as that value is returned. As for expressions being evaluated left to right, now you're questioning basic math ... Of course, you do have to take into account operator precedence, but once that is settles, each operation individually is always handled left to right. So, with these principles in place, "7 * 6" and "7 * 8" are the only logical choices to do the math. As far as the Math operators go, I love this quote: Remember basic arithmetic from school? These work just like those. Quote Link to comment Share on other sites More sharing options...
btherl Posted March 8, 2007 Share Posted March 8, 2007 The documentation says that PHP supports C-style pre-increment and post-increment operators.. and C's pre and post increment have exactly the problem I'm describing. It is certainly not cross-language accurate! Far from it, these operators behave differently between compilers and languages. The documentation states "Returns $a, then increments $a by one." for post-increment. It doesn't say immediate, which is exactly what causes compiler-dependent behaviour in C. The increment will happen before the next statement, but will it happen before evaluation of other children of the current expression is complete? In the absence of anything specific, you might assume that the rules are the same as those in C, where the operators came from. As for left to right evaluation, basic math doesn't specify left to right evaluation. Basic math does say that you can switch the left and right arguments of * and your result will be identical. In the example, switching the left and right arguments changes the result. Edit: Here's a summary of the problem in C: http://c-faq.com/expr/evalorder2.html Quote Link to comment Share on other sites More sharing options...
sneskid Posted March 8, 2007 Author Share Posted March 8, 2007 I've always been raised to believe ( I make it sound religious almost ) that: x++ means: take x as is, at this moment in time (not later) and apply that value in the current operation (one would expect the compiler to be using temporary variables at this point) THEN immediately increment it by 1. THEN continue with the rest of the operation. ++x means: increment x by 1 NOW, THEN use the new value, THEN continue the operation. operation: be it arithmetic, function calls, array index assignments, echo messages, whatever. Thus 42 and 56 are as expected. and $x=1; echo add($x++,$x++); should echo 3 and leave $x as 3. (and it does, yay) But I'm sure we can all agree that $x=1; $a[$x] = $x++; should be $a[1] = 1 NOT $a[2] = 1; (which I would accept if this was legal: $a[&$x] = $x++ and leave $x=2 So 4.3.10 has it right, and 5.1.4 got lazy? This behavior says "yea, I'll check that variable later, saves memory, PHP is way too bloated... who cares about the foundation of programming as we know it." and I have an issue with that, the kind of issue that makes me want to divorce PHP and marry Perl. Quote Link to comment Share on other sites More sharing options...
obsidian Posted March 8, 2007 Share Posted March 8, 2007 The documentation states "Returns $a, then increments $a by one." for post-increment. It doesn't say immediate, which is exactly what causes compiler-dependent behaviour in C. The increment will happen before the next statement, but will it happen before evaluation of other children of the current expression is complete? In the absence of anything specific, you might assume that the rules are the same as those in C, where the operators came from. OK, I agree with that statement. I was approaching from a logical perspective assuming that at the time the variable was accessed, it is incremented/decremented. You are correct that it is not explicitly stated that it is immediate. As for left to right evaluation, basic math doesn't specify left to right evaluation. Basic math does say that you can switch the left and right arguments of * and your result will be identical. In the example, switching the left and right arguments changes the result. Edit: Here's a summary of the problem in C: http://c-faq.com/expr/evalorder2.html Oh, contrair... ... Basic math tells us to follow the precedence of the operators as far as you can, and then move across the equation from left to right for the solution. Yes, with multiplication you happen to have the same solution if you switch your multiplicands (as with addition), but with subtraction and division, this is not the case, therefore, we follow some basic principles and move from left to right. Nobody in their right mind would try to argue that "4 - 3" could be either 1 or -1 since you could go from right to left. It's the exact same principle with all basic math operators. I actually wrote into the bug reporting for this to see what input I would get back from the "official" guys, and here's the response I got: Using and modifying the same variable when using post/pre- decrement/increment is undefined (and not only in PHP). Very helpful, huh? lol. btherl, I think we're back to your original recommendation being the most useful comment in this thread so far: Most languages leave such obscure questions undefined. Just don't do it Thanks Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.