Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.csd.uwm.edu!gem.mps.ohio-state.edu!ginosko!uunet!mfci!karzes From: karzes@mfci.UUCP (Tom Karzes) Newsgroups: comp.lang.c Subject: Re: Obfuscated SWAP: not portable! Message-ID: <1007@m3.mfci.UUCP> Date: 7 Sep 89 00:55:27 GMT References: <784@skye.ed.ac.uk> <1267@levels.sait.edu.au> <149@cpsolv.UUCP> <1400@levels.sait.edu.au> Sender: karzes@mfci.UUCP Reply-To: karzes@mfci.UUCP (Tom Karzes) Organization: Multiflow Computer Inc., Branford Ct. 06405 Lines: 56 In article <1400@levels.sait.edu.au> CCDN@levels.sait.edu.au (DAVID NEWALL) writes: >In article <149@cpsolv.UUCP>, rhg@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".)