EDIT: Alright, got it.
The first thing to do is that you should not use this code anyway. However, with its expansion, it becomes equivalent:
j = j ^ (i = i ^ (j = j ^ i));
(If we were to use a more complex expression like foo.bar++ ^= i , it would be important for ++ evaluated only once, but here I find it easier.)
Now the evaluation order of operands is always from left to right, so for starters we get:
j = 36 ^ (i = i ^ (j = j ^ i));
This (above) is the most important step. We ended up with 36 as LHS for the last XOR operation. LHS is not a " j value after RHS assessment".
The RHS of ^ evaluation includes a “one-level” expression, so it becomes:
j = 36 ^ (i = 25 ^ (j = j ^ i));
Then, looking at the deepest level of nesting, we can replace both i and j :
j = 36 ^ (i = 25 ^ (j = 25 ^ 36));
... which becomes
j = 36 ^ (i = 25 ^ (j = 61));
Assignment j to RHS is first assigned, but the result is still overwritten at the end, so we can ignore this: there are no further estimates of j until the final assignment:
j = 36 ^ (i = 25 ^ 61);
Now this is equivalent to:
i = 25 ^ 61; j = 36 ^ (i = 25 ^ 61);
Or:
i = 36; j = 36 ^ 36;
What will happen:
i = 36; j = 0;
I think that everything is correct, and he comes up with the correct answer ... apologize to Eric Lippert if some details about the evaluation order are slightly turned off :(
Jon Skeet Apr 07 2018-11-11T00: 00Z
source share