Obfuscated SWAP: not portable!

Tom Karzes karzes at mfci.UUCP
Thu Sep 7 10:55:27 AEST 1989


In article <1400 at levels.sait.edu.au> CCDN at levels.sait.edu.au (DAVID NEWALL) writes:
>In article <149 at cpsolv.UUCP>, rhg at cpsolv.UUCP (Richard H. Gumpertz) writes:
>> The exchange of x and y that has been under discussion:
>>     x ^= y ^= x ^= y
>> is non-portable because it depends on right-to-left evaluation which is NOT
>> specified in the C standard.
>
>I think it is specified.  (Perhaps it depends on whose standard you follow?)
>
>K&R I, page 19:
>     "The line
>        nl = nw = nc = 0;
>    sets all three variables to zero.  This is not a special case, but a
>    consequence of the fact that an assignment has a value and assignments
>    associate right to left."

No, it is not specified.  The K&R example is merely pointing out that the
assignment is parsed as:

    nl = (nw = (nc = 0));

To evaluate the outer assignment, both the destination and the right hand
side must be evaluated.  The order doesn't matter in this case.  The
right hand side (nw = (nc = 0)) is evaluated and its value is 0, which
is the value used in the outer assignment.

In the ^= case, the assignment is parsed as:

    x ^= (y ^= (x ^= y));

To evaluate the outer assignment, the destination must be evaluated (and
unlike the previous example, its value is also needed) and the right
hand side must be evaluated.  However, in this case the order DOES
matter.  If the right hand side is evaluated before x is evaluated,
then x will have the desired value (the value computed by x ^= y).
However, if x is evaluated before the right hand side, then the
x ^= y assignment in the right hand side will effectively have
been ignored.

When evaluating a ^= b, the compiler may generate any of the following:

    1.  evaluate a, evaluate b, xor, assign
    2.  evaluate b, evaluate a, xor, assign
    3.  some hybrid of 1 and 2

If it chooses the first sequence for the outer assignment in the original
^= example, the example will fail.

In fact, I'm not even certain that all side effects resulting from the
evaluation of a and b must be completed before the assignment takes
place.  (E.g., could x = 2 + (x = 5); perform the actual assignment
for (x = 5) after the outer assignment?  If it knows that the value
of (x = 5) is 5, could it delay the store to x?  I don't believe
assignment consitutes a sequence point in its own right.  One could
imagine "evaluate 5, evaluate 2, add, assign result, 7, to x, assign
previous result, 5, to x".)



More information about the Comp.lang.c mailing list