[comp.sys.atari.st] Megamax bug or crappy C ?

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;