Path: utzoo!mnetor!uunet!mcvax!tuvie!rcvie
From: rcvie@tuvie (ELIN Forsch.z.)
Newsgroups: comp.lang.c
Subject: Re: Autoincrement question
Message-ID: <548@tuvie>
Date: 7 Dec 87 10:00:58 GMT
References: <1507@ogcvax.UUCP>
Organization: TU Vienna EDP-Center, Vienna, AUSTRIA
Lines: 58

In article <1507@ogcvax.UUCP>, schaefer@ogcvax.UUCP (Barton E. Schaefer) writes:
> (I realize this might be similar to another question asked recently, but ...)
> 
> Another student here at OGC recently came to me with a question about the
> C autoincrement operator.  The following program is representative of the
> code he wrote, which did not do what he expected:
> 
>     struct foo { struct foo *tmp; char junk[32]; } foolist[4];
> 
>     main ()
>     {
> 	struct foo *bar;
> 
> 	bar = foolist;
> 	/* Do something with bar */
> 	bar->tmp = bar++;		/* This is the problem line */
> 	/* Do something else */
>     }
> 

This is really dangerous programming. The points where the left and where the
right "bar" are evaluated are implementation defined. The problem is similar to
another one, which a friend of mine had some time ago. He tried to pack as much
as possible into the control part of a while loop using the following statement:

while (a[i]=b[i++])
  ;

Things were even worse here, as the program behaved even differently depending
on whether it was compiled with the optimization option or not. Non optimized
everything worked as expected but in the optimized version only for the first
assignment "i" was incremented after the assignment, for all the following
assignments it was incremented after the evaluation of "b[i]" but before the 
assignment. Nevertheless this behaviour was in the sense of both K&R and ANSI.
The only thing you can trust on, is that the *operand* of the increment
operator is evaluated before its incrementation. One way to achieve the desired
behaviour is, as you suggested yourself, to write:

> What he really wanted was the equivalent of
> 	bar->tmp = bar;
> 	bar++;

and not (for the same reasons stated above):

> 	(bar++)->tmp = bar;

If there is any necessity to have the whole semantic in one *expression*, use
the comma operator, as

bar->tmp = bar, bar++;

This operator *guarantees* the sequential evaluation of its operands from
left to right.

In real life: Dipl.Ing. Dietmar Weickert
              ALCATEL Austria - ELIN Research Center
              Floridusg. 50
          A - 1210 Vienna / Austria