tulp@klipper.UUCP (05/20/87)
Try this piece of code with the Megamax C compiler. I am not sure whether
this is a bug (and if so I don't remember if it has been reported yet or
if it was fixed in a newer release; I use Version 1.1), maybe this is just
an example of bad C programming. I also tried this test with the Alcyon
(DRI) C compiler and this compiler did translate it the way I thought it
should be.
---
#include "stdio.h"
#include "osbind.h"
main()
{ int array[7];
register int i;
array[3] = 10;
i = 3;
while (i > 0)
array[i - 1] = array[i--] - 1; /* Trouble here. */
i = 3;
while (i < 6)
array[i + 1] = array[i++] + 1; /* And trouble here. */
for (i = 0;i< 7;i++)
printf("Array index %d is %d.\n",i,array[i]);
Cconin();
}
---
I looked at the code the compiler brewed and it appeared that first it
computes array[i--] - 1, including the post decrement, and then (with i
already decremented !) it computes array[i - 1]. So array[i - 1], really
becomes array[i - 2] ! As far as I know the post decrement should take
place after the entire expression is evaluated (the Alcyon compiler does
that). But I am not absolutely sure whether K & R is unambiguously clear
about this (I thought it said that the decrement takes place after the
assignment is done, but I don't have K & R laying around here, sorry).
Anyone ?
Of course I know that the expression could much easier be written as a for
loop. But this phenomenon occurred in a different context and I tried to
make a simple and clear test.
Drive and Megamax carefully,
Eduard Tulp tulp@cs.vu.nl
--------------------------------------------------------------------------
Live every day as if it were your last,
One day you will be right.
dillon@CORY.BERKELEY.EDU (Matt Dillon) (05/20/87)
> array[i - 1] = array[i--] - 1; /* Trouble here. */ >I looked at the code the compiler brewed and it appeared that first it >computes array[i--] - 1, including the post decrement, and then (with i >already decremented !) it computes array[i - 1]. So array[i - 1], really >becomes array[i - 2] ! As far as I know the post decrement should take >place after the entire expression is evaluated (the Alcyon compiler does >that). But I am not absolutely sure whether K & R is unambiguously clear >about this (I thought it said that the decrement takes place after the >assignment is done, but I don't have K & R laying around here, sorry). >Anyone ? Totally and Completely Wrong. You can make no assumptions as to the order of evaluation for most C statements. Except for &&, ||, the comma operator, and a very few other statements/operations, the order of evaluation is totally dependant on the C compiler used. The definition for post increment or decrement is that the particular variable's value is used in that instance and then decremented or incremented by the end of the expression (segment). You can't even assume that the order of evaluation for an assignment is right-side-first: *ptr = *ptr++ Could either evaluate the right side first, or evaluate the effective address of the left side, then the right side, then do the assignment. a && b && c a is evaluated if TRUE b is evaluated, and if that is TRUE c is evaluated. Thus, char *a=NULL; if (a && *a) ... is perfectly valid C.... the *a is not evaluated if a is NULL. a || b || c a is evaluated if FALSE b is evaluated, etc... (a,b) a is evaluated. b is evaluated, the result of the expression is b. So the only time you can use postincrement/postdecrement and *know* the evaluation order would be in something like this (example): if (a++ || b++ || c++) .. for (i++, j = i; j < 10; j++) .. -Matt P.S. somebody care to check if the Alcyon compiler does the right thing for ||,&&, and the comma operator??
tom@cogpsy.UUCP (05/21/87)
In article <756@klipper.cs.vu.nl> tulp@cs.vu.nl (Tulp E) writes: >if it was fixed in a newer release; I use Version 1.1), maybe this is just >an example of bad C programming. I also tried this test with the Alcyon <some deletes lines> > array[i - 1] = array[i--] - 1; /* Trouble here. */ <some deletes lines> > array[i + 1] = array[i++] + 1; /* And trouble here. */ lint test.c test.c(11): warning: i evaluation order undefined test.c(14): warning: i evaluation order undefined Also K&R make it clear that the evaluation of the above code is implementation dependent. Tom Vijlbrief ============================================================================= TNO Institute for Perception (Netherlands organisation for applied scientific research) Cognitive Psychology Research Group P.O. Box 23 Phone: +31 34 63 14 44 3769 DE Soesterberg E-mail: tnosoes!cogpsi!tom@mcvax.cwi.nl The Netherlands {seismo|...}!mcvax!tnosoes!cogpsi!tom
pes@bath63.UUCP (05/21/87)
K&R have almost the identical example, at the end of chapter 2. The quick answer is, they're both right. From K&R: 'In any expression involving side effects, thre can be subtle dependencies on the order in which variables taking part in the expression are stored. One unhappy situation is typified by the statement a[i] = i++; The question is whether the subscript is the old value of i or the new. The compiler can do this in different ways, and generate different answers depending on its interpretation. When side effects (assignment to actual variables) takes place is left to the discretion of the compiler, since the best order strongly depends on machine architecture. The moral of this discussion is that writing code which depends on order of evaluation is a bad practice in any language.' I'd say that applies to your slightly fancier example, as well, meself. And I *believe* that even the proposed ANSI standard doesn't tighten this up much, if at all -- though I don't track it very closely so may be wrong.
burris@ihuxz.ATT.COM (Burris) (05/22/87)
In article <756@klipper.cs.vu.nl>, tulp@cs.vu.nl (Eduard Tulp) writes: > Try this piece of code with the Megamax C compiler. I am not sure whether > this is a bug... > > main() > > { . . . > > while (i > 0) > array[i - 1] = array[i--] - 1; /* Trouble here. */ . . . > while (i < 6) > array[i + 1] = array[i++] + 1; /* And trouble here. */ . . . > } Function calls, nested assignments, and increment and decrement operators cause "side effects"... ...One unhappy situation is typified by the statement a[ i ] = i++; ...When side effects (assignment to actual variables) takes place is left to the discretion of the compiler... The moral of this discussion is that writing code which depends on order of evaluation is a bad programming practice in any language...
ftw@datacube.UUCP (05/26/87)
There is a notion of "sequence points" in the ANSI draft standard. This notion addresses the kind of problems that might be had with an expression such as: a[i] = ++i;