Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!batcomputer!cornell!uw-beaver!milton!ogicse!intelhf!ichips!iwarp.intel.com!inews!pima!bhoughto From: bhoughto@pima.intel.com (Blair P. Houghton) Newsgroups: comp.std.c Subject: More Re: Function Argument Evaluation argument Message-ID: <3547@inews.intel.com> Date: 29 Mar 91 06:13:49 GMT Article-I.D.: inews.3547 References: <17936@crdgw1.crd.ge.com> <15607@smoke.brl.mil> <17983@crdgw1.crd.ge.com> Sender: news@inews.intel.com Organization: Intel Corp, Chandler, AZ Lines: 87 In article <17983@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: >But the only reason you were able to produce an order of evaluation that >resulted in "200 200" is because the program did something it should never >have done in the first place, which was to modify p twice between sequence >points. He's got a definite point, here [1]. Neither of the expressions in this list of function arguments is a full-expression [2], and neither contains any of the operators that define sequence points [3], so the only sequence-point around is the one before the function-call [4]. Thus, using p twice in an lvalue context renders the behavior undefined [5]. [1] ANSI X3.159-1989, sec. 3.3, p. 39, ll. 5-7. [2] Ibid., Appendix B, p. 189. [3] Ibid. [4] Ibid (dangit! no line numbers! ). [5] See also p. 39, footnote 34. Maybe this also answers John Gingerich's question (and if I still didn't understand it then I really don't understand it) about "is it undefined?" I was wrong. The arguments' behavior is undefined, so the statement's is undefined, so the program's is undefined, and the compiler can tune up its pipes and start tooting "Daaaaaii-seeeee, Daaai-seee, give me your an-swer true..." [6] >I would be very interested in seeing a program whose behavior >was *not* undefined, yet could arbitrarily produce either of two >drastically different outputs depending solely on the unspecified >order of evaluation. Insert a sequence-point: char *x = "foo", *y = "bar"; printf("\t%s %s\n", (p = x)?p:"(nil)", (p = y) ); Now the behavior is defined, since there's a sequence point after the first assignment to p, but no way to tell which of the p's is returned after either question mark. It is certain, however, that the second argument must return "bar", since the first assignment was before the sequence point at the `?', and everything else is after that sequence point and before the function-call sequence point. This will print either foo bar or bar bar Depending on the order in which the placing of the first argument on the stack and the assignment of y to p are performed. It seems to me, though, that since I asked for "p" and not "the result of p only due to the first argument", then the value should have to wait for the side-effects (the actual storage is a side-effect of assignment (sec. 3.3.16, p. 54, ll. 14-16)) of other argument-expressions before it is placed on the stack. I didn't need the obfuscation of the `?:', either. f(p,p=y); faces a similar nonspecificity of the values of the arguments at the sequence point. There's no rule against changing a stack value multiple times between sequence points, either, so the stack could get the first p, then the compiler could say "oops, p changed due to an assignment, better fix the first one" and the new value could be put on the stack. If a compiler does this, I'd like to have it. It probably gets the rest of the standard right, too. But I can't count on it, since the standard moots this interpretation. --Blair "[6] I get it. '2001: A Space Odyssey' is all about the perils of nonconformance. :-) :-) Kubrick, what a visionary!"