maart@cs.vu.nl (Maarten Litmaath) (05/27/89)
chris@mimsy.UUCP (Chris Torek) writes:
\...
\But e1?e2:e3 *can* be turned into (e1&&e2 || !e1&&e3)
But what if e1 == *p++?
--
"`Goto considered harmful' considered |Maarten Litmaath @ VU Amsterdam:
harmful" considered harmful! |maart@cs.vu.nl, mcvax!botter!maart
chris@mimsy.UUCP (Chris Torek) (05/31/89)
[me:] >>But e1?e2:e3 *can* be turned into (e1&&e2 || !e1&&e3) In article <2632@solo1.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >But what if e1 == *p++? In the original bogus article (<17722@mimsy.UUCP> [someday to be mimsy.umd.edu]) I included various conditions, such as `no side effects' and `used in a boolean context'. I figured these were obvious enough in the followup not to require another explication. . . . -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
dg@lakart.UUCP (David Goodenough) (06/07/89)
From article <2632@solo1.cs.vu.nl>, by maart@cs.vu.nl (Maarten Litmaath): > chris@mimsy.UUCP (Chris Torek) writes: > \... > \But e1?e2:e3 *can* be turned into (e1&&e2 || !e1&&e3) > > But what if e1 == *p++? Simple: ((a = *p++) && e2 ) || (!a && e3) -- dg@lakart.UUCP - David Goodenough +---+ IHS | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@xait.xerox.com +---+
spl@mcnc.org (Steve Lamont) (06/09/89)
In article <562@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes: >From article <2632@solo1.cs.vu.nl>, by maart@cs.vu.nl (Maarten Litmaath): >> chris@mimsy.UUCP (Chris Torek) writes: >> \... >> \But e1?e2:e3 *can* be turned into (e1&&e2 || !e1&&e3) >> >> But what if e1 == *p++? > >Simple: > >((a = *p++) && e2 ) || (!a && e3) Is right to left evaluation mandated in this case? It seems to me that I've been bitten by things like this before, either by non-standards conforming compilers, ambiguous definition in the standard, my own stupidity, or all of the above. In any case, it seems that defensive programming might dictate something like (a = *p++), ( ( a && e2 ) || (!a && e3) ) What say the gurus? Or is this an RTFM? -- spl Steve Lamont, sciViGuy EMail: spl@ncsc.org North Carolina Supercomputing Center Phone: (919) 248-1120 Box 12732/RTP, NC 27709
gwyn@smoke.BRL.MIL (Doug Gwyn) (06/09/89)
In article <4675@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: >>((a = *p++) && e2 ) || (!a && e3) >Is right to left evaluation mandated in this case? It seems to me that >I've been bitten by things like this before, either by non-standards >conforming compilers, ambiguous definition in the standard, my own >stupidity, or all of the above. In any case, it seems that defensive >programming might dictate something like ... There has never been any ambiguity about the correct sequence of operations during evaluation of such an expression (except when `p' is used in `e2' or `e3'). The outermost operator is ||; to evaluate ex1||ex2 the compiler is obliged to generate code that evaluates ex1 first, and ex2 only if necessary. To evaluate ex1, here ((a=*p++)&&e2), the stuff within the outermost parens must be evaluated. To evaluate that, the rules require that (a=*p++) must be evaluated first, and e2 only if necessary. ... If ex2, here (!a&&e3), is required to be evaluated, that is after ex1 has been completely evaluated. There is no ambiguity. The point of C having assignment expressions, postincrement operators, short-circuit evaluators, and so forth is precisely to avoid having to use techniques such as your "defensive programming" example. Of course some vendor might offer what is called a "C compiler" that gets basic expression evaluation wrong, but if so, it would be virtually useless for the vast majority of existing C source code. I don't think you really need to guard against totally broken compilers; if you start worrying about that, there is no end to the things that "might" be done wrong..
spl@mcnc.org (Steve Lamont) (06/10/89)
In article <10387@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <4675@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: >>>((a = *p++) && e2 ) || (!a && e3) >>Is right to left evaluation mandated in this case? It seems to me that >> [my paranoia deleted to save embarrassment] >There has never been any ambiguity about the correct sequence of >operations during evaluation of such an expression (except when >`p' is used in `e2' or `e3'). The outermost operator is ||; to >evaluate ex1||ex2 the compiler is obliged to generate code that Right. The FM (K&R, First Edition, p. 19) sez: "Expressions connected by && or || are evaluated from left to right, and it is guaranteed that evaluation will stop as soon as truth or falsehood is known." I should've looked before posting. The thing I like about this group is the sense of humility it brings to me! >existing C source code. I don't think you really need to guard >against totally broken compilers; if you start worrying about that, >there is no end to the things that "might" be done wrong.. Don't know if I exactly agree with that. I've *had* to use some fairly broken compilers... :-) -- spl Steve Lamont, sciViGuy EMail: spl@ncsc.org North Carolina Supercomputing Center Phone: (919) 248-1120 Box 12732/RTP, NC 27709
dg@lakart.UUCP (David Goodenough) (06/12/89)
gwyn@smoke.BRL.MIL (Doug Gwyn) sez: > In article <4675@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: >>>((a = *p++) && e2 ) || (!a && e3) >>Is right to left evaluation mandated in this case? It seems to me that >>I've been bitten by things like this before, either by non-standards >>conforming compilers, ambiguous definition in the standard, my own >>stupidity, or all of the above. In any case, it seems that defensive >>programming might dictate something like ... > > There has never been any ambiguity about the correct sequence of > operations during evaluation of such an expression (except when > `p' is used in `e2' or `e3'). Huh??? - if I use p in e2 or e3, my compiler had better use the value _AFTER_ the *p++, otherwise I'm going to ask for my money back. In the above code fragment if _ANYTHING_ is executed before the a = *p++ then the compiler is broken. The same applies to: if ((a = *p++) ? e2 : e3) The a = *p++ part has to be done first so that the compiler knows which of e2 and e3 to do. Of course if your going to tell me that the standard says that the a = *p and the p++ may happen at different times (i.e. the p++ after e2), then I'm going to say the standard is broken. -- dg@lakart.UUCP - David Goodenough +---+ IHS | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@xait.xerox.com +---+
karl@haddock.ima.isc.com (Karl Heuer) (06/15/89)
In article <568@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes: >gwyn@smoke.BRL.MIL (Doug Gwyn) sez: >>[The expression ((a = *p++) && e2 ) || (!a && e3) is well-defined] >>(except when `p' is used in `e2' or `e3'). > >Huh??? ... my compiler had better use the value _AFTER_ the *p++ ... You're right; this is still unambiguous. The pANS specifies that there is a sequence point after the evaluation of the first operand of &&, ||, or ?:. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
dfp@cbnewsl.ATT.COM (david.f.prosser) (06/15/89)
In article <568@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes: ]gwyn@smoke.BRL.MIL (Doug Gwyn) sez: ]> In article <4675@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: ]>>>((a = *p++) && e2 ) || (!a && e3) ]>>Is right to left evaluation mandated in this case? It seems to me that ]>>I've been bitten by things like this before, either by non-standards ]>>conforming compilers, ambiguous definition in the standard, my own ]>>stupidity, or all of the above. In any case, it seems that defensive ]>>programming might dictate something like ... ]> ]> There has never been any ambiguity about the correct sequence of ]> operations during evaluation of such an expression (except when ]> `p' is used in `e2' or `e3'). ] ]Huh??? - if I use p in e2 or e3, my compiler had better use the value ]_AFTER_ the *p++, otherwise I'm going to ask for my money back. In the ]above code fragment if _ANYTHING_ is executed before the a = *p++ then ]the compiler is broken. The same applies to: ] ] if ((a = *p++) ? e2 : e3) ] ]The a = *p++ part has to be done first so that the compiler knows which ]of e2 and e3 to do. Of course if your going to tell me that the standard ]says that the a = *p and the p++ may happen at different times (i.e. the ]p++ after e2), then I'm going to say the standard is broken. ]-- ] dg@lakart.UUCP - David Goodenough +---+ ] IHS | +-+-+ ] ....... !harvard!xait!lakart!dg +-+-+ | ]AKA: dg%lakart.uucp@xait.xerox.com +---+ David is correct: There are sequence points at the appropriate operators in these expressions. Because all pending updates must occur between the previous and the next sequence point, the update to p in each of the following expressions must occur prior to the evaluation of e2 or e3: (a = *p++) ? e2 : e3 /* ^ sequence point */ ((a = *p++) && e2) || (!a && e3) /* ^ ^ ^ sequence points */ But in ((a = *p++) & e2) | (!a & e3) there is no guarantee about the update of p with respect to the evaluation of the rest of the expression. Dave Prosser ...not an official X3J11 answer...
gwyn@smoke.BRL.MIL (Doug Gwyn) (06/17/89)
In article <568@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes: >gwyn@smoke.BRL.MIL (Doug Gwyn) sez: >> In article <4675@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: >>>>((a = *p++) && e2 ) || (!a && e3) >> There has never been any ambiguity about the correct sequence of >> operations during evaluation of such an expression (except when >> `p' is used in `e2' or `e3'). >... Of course if your going to tell me that the standard >says that the a = *p and the p++ may happen at different times (i.e. the >p++ after e2), then I'm going to say the standard is broken. No, the Standard specifies that there is a sequence point after the evaluation of the first operand of && (also ||). However, we were discussing pre-Standard C and what were universally understood to be the rules back then versus what was considered not clearly specified. In K&R1, the sequencing of side effects was not clearly specified, and consequently some C implementations deferred the side effects in surprising ways, which is the point of my parenthetical comment above. X3J11 came up with the concept of "sequence points" to permit accurate constraint specification in this area.
andrew@alice.UUCP (Andrew Hume) (06/19/89)
i would second doug's comment.
a technique i have found useful (but not usable all the time) is for
routines to return a char *. on success this is 0, on error it is the actual
error message. simple to use, e.g.
if(e = poot(args)){
fprintf(stderr, "%s\n", e);
exit(1);
}