4

What is the precidency and associtivity for increment operator and assignment operator for the block of code

$a=array(1,2,3);
$b=array(4,5,6);
$c=1;

$a[$c++]=$b[$c++];

print_r($a);

As per the execution it outputs

 Array
       (    
         [0] => 1
         [1] => 6
         [2] => 3
       )

But I am not able to understand how array $a index 1 holds the value of array $b index 2 value. Can anybody explain the scenario how the execution happens?

Jenz
  • 8,280
  • 7
  • 44
  • 77
bikashphp
  • 165
  • 3
  • 10
  • Isn't this a case of *undefined behaviour*? See http://stackoverflow.com/questions/949433/why-are-these-constructs-undefined-behavior?lq=1. – SukkoPera Sep 22 '14 at 09:18
  • Can you maybe clarify what exactly is puzzling for you about this behaviour? Is it the behaviour of `++` or the execution order? What result would you have expected? – deceze Sep 22 '14 at 09:31
  • Hi deceze the most puzzling is the which side post increment should be calculated first? But as per the precedence table the increment operator has right associativity. So in the question in the fourth line $c++ in the right hand side of the assignment operator should execute first i.e. $b[$c++] should be executed first. – bikashphp Sep 22 '14 at 09:49

3 Answers3

2

PHP is (once again) different from other languages in that the left part of an assignment evaluates first. Simple proof:

$a[print 1] = $b[print 2]; // what does this print?

According to http://3v4l.org/, this code:

$a = array(); $b = array(); $c = 1;
$a[$c++]=$b[$c++];

generated following opcodes:

compiled vars:  !0 = $a, !1 = $b, !2 = $c
line     # *  op                           fetch          ext  return  operands
---------------------------------------------------------------------------------
   2     0  >   INIT_ARRAY                                       ~0      
         1      ASSIGN                                                   !0, ~0
         2      INIT_ARRAY                                       ~2      
         3      ASSIGN                                                   !1, ~2
         4      ASSIGN                                                   !2, 1
   3     5      POST_INC                                         ~5      !2
         6      POST_INC                                         ~7      !2
         7      FETCH_DIM_R                                      $8      !1, ~7
         8      ASSIGN_DIM                                               !0, ~5
         9      OP_DATA                                                  $8, $9
        10    > RETURN                                                   1

The opcode 5 is the left $c++, and the opcode 6 is the right $c++. So the final assignment (opcode 8) is evaluated as

$a[1] = $b[2];

which results in (1,6,3).

georg
  • 211,518
  • 52
  • 313
  • 390
0

The ++ post increment operator first returns the value and afterwards (post) increments the value. I.e. $c++ returns the value of $c, then increments $c.

It is then obviously executing like this:

$a[$c++] =

Here the value of $c++ is taken as 1, but $c is then post-incremented to 2.

$b[$c++]

Here the value of $c++ is taken as 2, and then $c is post-incremented to 3 (which nobody cares about anymore though).

So the expression is equivalent to:

$a[1] = $b[2];

For contrast, the pre-increment operator ++$var first increments the value, then returns the new incremented value. So $a[++$c] = $b[++$c] would result in a Undefined offset 3 in $b error.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • But assigment has right associativity, why $с++ have counted from left? – sectus Sep 22 '14 at 09:19
  • Logical associativity and evaluation order aren't necessarily the same thing. Associativity refers to *how* two operands will be added together, not *when* either operand's *expression* is evaluated. – deceze Sep 22 '14 at 09:23
  • Hi deceze as per your defination what is the logical associativity? Then if there is such concept then what is the concept of left to right and right to left associativity while computing the operation? – bikashphp Sep 22 '14 at 09:36
  • @bika The associativity among operators in this case merely states that the entirety of the right hand side will be assigned to the single variable on the left; i.e. `$a = $b + $c + $d` means `$b + $c + $d` will be assigned to `$a`, not possibly `($a = $b + $c) + $d`. Independent of that is the evaluation order of each operand, i.e. nothing defines in which order all these functions are called before the assignment happens: `$a[foo(bar())] = baz(blarg())`. – deceze Sep 22 '14 at 09:47
0

It's called undefined order of evalution.

Operator precedence and associativity only determine how expressions are grouped, they do not specify an order of evaluation. PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code.

http://php.net/manual/en/language.operators.precedence.php#example-130

But current behaviour have never changed: http://3v4l.org/b1Y1X

sectus
  • 15,605
  • 5
  • 55
  • 97