mp@mit-eddie.UUCP (Mark Plotnick) (12/26/83)
dave@taurus notes: Uh-uh: if(*in++ == *in++) ... Also, for those of little faith, there are actually C compilers that will take the non-obvious meaning of this (e.g. the PDP-11 cc), and do the tests then do both increments in one go after the statement, so BE WARNED. I just tried this with the V7 cc, 4.1bsd pcc, and VAX-11 C compilers, and in each case two increments were done. The reference manual is vague here, but a good rule of thumb is that foo++ is equivalent to ((foo=foo+1)-1). I don't know of any exceptions to this off-hand, although I heard that a pcc author was once thinking of delaying the postincrement of function args until after the function call [i.e. f(i++) would be equivalent to (temp=f(i),i++,temp) ]. Since there are still quite a few C compilers being written from scratch out there, it would really help if someone were to come up with a precise, consistent definition for how the postincrement and postdecrement operators should behave. Ditto for enum, void, unsigned chars, non-integer bitfields, etc. Mark
minow@decvax.UUCP (Martin Minow) (12/27/83)
Mark Plotnik asks for a "precise, consistent definition" of the semantics of ++ and -- (among other things). The definition is "compiler dependent", but all side effect operators will be evaluated when control passes to the next statement. (It may be the case that side-effect operations will be evaluated before passing over , && or ||, but I wouldn't bet on it. Vax-11 C (on VMS) is very willing to evaluate auto-increment operators at "unusual" times. For example, consider the following: int stack[123]; /* Evaluation stack */ int *stack_pointer = stack; #define push(x) (*--stack = x) /* Stuff into the stack */ #define pop() (*stack++) /* Get from the stack */ int eval(operator) { switch (operator) { ... case OP_ADD: push(pop() + pop()); ... You may think that "*--stack = *stack++ + *stack++;" will "do the right thing", but it is (by demonstration) compiler dependent. (I found that out the hard way -- the original had the misleading comment "don't need a temp variable since addition is commutative"). The correct expression of the above is: temp = pop(); temp += pop(); push(temp); Martin Minow decvax!minow
jreuter@cincy.UUCP (Jim Reuter) (12/28/83)
dave@taurus notes: Uh-uh: if(*in++ == *in++) ... Also, for those of little faith, there are actually C compilers that will take the non-obvious meaning of this (e.g. the PDP-11 cc), and do the tests then do both increments in one go after the statement, so BE WARNED. mp@mit-eddie replies: I just tried this with the V7 cc, 4.1bsd pcc, and VAX-11 C compilers, and in each case two increments were done. (The implied meaning is that they were done in the proper place. They are, I just tested it.) The real problem here is the ORDER of the increments. In this example, order would not matter. A nice simple example of ordering problems shows up in the v7 Ritchie compiler: int i = 0; printf(" %d %d %d %d\n", i++, i++, i++, i++ ); which produces 3 2 1 0 Jim Reuter (decvax!cincy!jreuter)
donn@sdchema.UUCP (Donn Seeley) (01/04/84)
Not that this constitutes a holy war, but I strongly agree with Dave Lukes that the order of evaluation of side effects is (and should be) undefined. Even if side effects had a dependable order of evaluation, programs that depended on this order would be very difficult for the programmer in the street to interpret. I'm not (necessarily) an advocate of functional programming but I don't think that this attitude is unreasonable. Also, by restricting the order of evaluation of these side effects you might disallow some (otherwise) reasonable optimizations. I really wanted to contribute an example of a compiler difference in order of evaluation of side effects. This incident actually happened -- you can try it for yourself if you don't believe it. Some poor researcher's C program to convert plot data ran on V6 on an 11/40 but broke under 4.1 on the VAX. (We ran phototypesetter V7 C on the 11/40, if it makes any difference.) When I looked at his program I discovered code like the following: ... int data[8]; int *R; int count; ... R = data; count = *R++ + *R++ + *R++ + *R++ + *R++ + *R++ + *R++ + *R++; ... Some unthinking systems programmer had casually informed the poor researcher that pointer references were faster than subscript indirection. From there it was a short step to concluding that side effects are done from left to right (obvious, huh? -- well, at least you TYPE the side effects in from left to right). When he compiled and ran the program on V6, it worked just as he expected. Unfortunately the VAX compiler (with -O) does all of the increments AFTER doing all of the additions... (And clumsily, too: it does all the increments separately instead of conflating them into a single add.) So, yes, commonly used C compilers DO differ in order of evaluation of postincrement and other side effects. Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn