CSvax:Pucc-H:Physics:crl (01/26/83)
#N:pur-phy:15700005:000:726 pur-phy!crl Jan 26 11:02:00 1983 I have just noticed a bug in the Ritchie C compiler (or at least an example of it being too smart for its own good). Consider the following: main() { if (foo()*0); } foo() { printf("in foo\n"); } The compiler thinks: "Well, foo() * 0 is always false, so I won't even compile the if statement." I don't think that this should be the way it compiles, what do you people think? (I know no sane person would do this, but I had to fix some software I got from somewhere else where in a complicated series of #ifdefs someone had decided that this was the easiest way to have the if always fail. YECCH!) The "bug" does not seem to exist in our version of pcc. Charles LaBrec pur-ee!Physics:crl purdue!Physics:crl
wsh (01/27/83)
**************************************************************************
I have just noticed a bug in the Ritchie C compiler (or at least
an example of it being too smart for its own good)...
**************************************************************************
We quote from the Gospel according to Kernighan and Ritchie (p. 185):
"Otherwise the order of evaluation of expressions is undefined. In
particular the compiler considers itself free to compute subexpressions
in the order it believes most efficient, even if the subexpressions involve
side effects. The order in which side effects take place is unspecified.
Expressions involving a commutatiave and associative operator (*, +, &,
|, ^) may be rearranged arbitrarily, even in the presence of parentheses;
to force a particular order of evaluation an explicit temporary must be
used."
The lesson seems to be that the code cited in the original article
is not portable (assuming that the side effect from foo () is expected),
and that the Ritchie compiler is acting entirely correctly (if only
because the C language specification specifically relieves the compiler
of responsibility for any particular implementation). Here is a case of
the code (rather than the compiler) being too smart for its own good
(again, assuming that the code expects foo () to be executed). A
reasonable way to get around this problem is to use the comma operator;
the expression
if (foo (), 0)
has the desired effect, in a well-defined way.
Willie Heck
abi - holmdel
npoiv!hou5f!wsh
rcj (01/27/83)
if (foo()*0) ... INSANITY!!! The MAD Programmer alias: Curtis Jackson ...!floyd!burl!rcj ...!sb1!burl!rcj ...!mhuxv!burl!rcj
leichter (01/28/83)
The text you quote explicitly gives the compiler to RE-ARRANGE expressions and evaluate their component parts in any order it likes. It DOES NOT, as it stands, give it permission to skip the evaluation of any part. I think if you look up the discussion of, say, & vs. &&, you will find some remarks to the effect that && only evaluates as much as it needs, but & evaluates both arguments. What, then, is one to make of 0&foo()? -- Jerry decvax!yale-comix!leichter
CSvax:Pucc-H:Physics:crl (01/30/83)
#R:burl:-5400:pur-phy:15700006:000:1755 pur-phy!crl Jan 29 14:35:00 1983 In bringing this case up originally, I didn't see that the way the Ritchie compiler optimized the evaluation of the if expression out would make much of a difference in any *sane* code. However, in thinking about it some more, I believe that there is a possibility that this may come up in some software somewhere. Suppose one was writing a program that was to be distributed, and for this reason, you include 2 tunable parameters A and B that are #define's. It would then not seem like a potential disaster to say: if (i++ * (A-B) > 20) { /* is i incremented? */ . . . would it? Who would expect that if A==B, the i++ would never be executed at all? In fact, since I postulated that this code is distributed, the bug might be just about impossible to track down. In my case, I was just lucky because it wasn't A-B but a hard-coded '0'. Sure programmers are warned about counting on side-effects, but we all use them when there doesn't seem to be a problem. The above would work on pcc, but also on R's cc, except at an installation who set A=B. Furthermore, nary a message is printed by either the compiler or lint about the non-evaluation of the "if" test or the unreachability of the "then" portion. So the question remains: is it a bug, or not? While it is true that expressions may be re-ordered, I agree with yale-comix!leichter that the compiler should not be allowed to *avoid* the evaluation of a non-constant expression. If A and B above were variables and not constants, I definitely would not want a compiler to evaluate (A-B), decide it was == 0, and not perform the i++. While it is very clear here that that would be a bug, the two cases are analogous, at least to me. Charles LaBrec pur-ee!Physics:crl purdue!Physics:crl
sjb (01/31/83)
The reference manual clearly states that ++ has a higher precedence than -. Therefore, if the compiler throws the block away because A==B, it wouldn't seem to be following the rules of precedence.
norskog (02/02/83)
#R:pur-phy:15700005:fortune:16200003:000:155 fortune!norskog Feb 1 21:39:00 1983 This process is known as "constant folding" and is a part of any reasonably sophisticated compiler. En otras palabras, 'tis a feature. Lance Norskog