[comp.lang.c] Beautiful side-effects!

rolfe@dsuvax.uucp (Timothy J. Rolfe) (06/26/91)

Beautify, beautiful side effect!!

As it stands, "q = q++;" SHOULD leave q unchanged:  evaluating the
right hand side we get a value (q BEFORE the increment).  That is
the value that is supposed to go to the left hand side.  The question
is WHEN the post-increment is done.

On a MicroVAX-II under Ultrix we get it BOTH ways, depending on whether
we use the cc, gcc, or vcc compiler --- plain cc, GNU's cc, and VAX
native C.

We can even go better:

        main()
        {
           int q=5, inc=10;
           void kludge();
        
           kludge (q, inc);
        }
        
        void kludge(q, inc)
        int q, inc;
        {
           q = q++ + inc;
           printf ("%d\n", q);
        }

The extra level is to get around the #@$%#@ vcc compiler's optimizing
q = q++ + inc; into a simple q = 15; (since it knows the values!).

cc- and gcc-compiled versions generate an answer of 16; vcc-compiled
version generates an answer of 15.

gcc-generated machine code for kludge:

.globl _kludge
_kludge:
	.word 0x0
	addl2 8(ap),4(ap)      ; <== calculated straight into q
	incl 4(ap)             ; <== then do the post-increment
	pushl 4(ap)            ; Assorted stuff for printf
	pushab LC0
	calls $2,_printf
	ret

vcc-generated machine code for kludge:

kludge:
	.entry	kludge,^m<>
	movl	4(ap),r2       ; <== get the q value
	incl	4(ap)          ; <== then do the post-increment	
	addl3	8(ap),r2,4(ap) ; <== finally calculated into q
	pushl	4(ap)          ; Assorted stuff for printf
	pushal	$CHAR_STRING_CONSTANTS
	calls	#2,printf
	ret	

                                                        --- Tim Rolfe
                                             <a.k.a. ROLFE@SDNET.BITNET>

sasrer@unx.sas.com (Rodney Radford) (06/27/91)

In article <1991Jun26.154734.14439@dsuvax.uucp> rolfe@dsuvax.uucp (Timothy J. Rolfe) writes:
>Beautify, beautiful side effect!!
>
>As it stands, "q = q++;" SHOULD leave q unchanged:  evaluating the
>right hand side we get a value (q BEFORE the increment).  That is
>the value that is supposed to go to the left hand side.  The question
>is WHEN the post-increment is done.

ANSII C says the behaviour of the above line is indetermined 
(ie: implementation dependent), and should be avoided in writing portable
C programs (to more that one machine, or more that one compiler, or 
possibly to different versions of the same compiler...).

The reason ANSII could not set a standard on this is that through the years
so many different versions of C existed and handled this differently. Also
should be avoided statements such as:

       array[i++] = i;

         --- or ---

       function(++k,k,k++)

These are just other examples of indeterminate side-effect expressions....
-- 
Rodney Radford          || Computer Graphics/Imaging
sasrer@unx.sas.com      || SAS Institute, Inc.
(919) 677-8000 x7703    || Cary, NC  27513

kurt@tc.fluke.COM (Kurt Guntheroth) (06/27/91)

> "q = q++;" SHOULD leave q unchanged:  evaluating the
> right hand side we get a value (q BEFORE the increment).  That is
> the value that is supposed to go to the left hand side.  The question
> is WHEN the post-increment is done.

K&R says nothing about when the increment's side effect is processed, and
ANSI says specifically that it is undefined.  The side effect may be applied
AFTER the assignment.  You are probably used to the informal PDP11 semantics
where q++ generates an increment instruction, but no all architectures or
compilers choose this method.  A better example is 

    *p++ = *p++;

which has three side effects that may be processed in arbitrary order.

madd@world.std.com (jim frost) (06/30/91)

kurt@tc.fluke.COM (Kurt Guntheroth) writes:
>> "q = q++;" SHOULD leave q unchanged

>K&R says nothing about when the increment's side effect is processed, and
>ANSI says specifically that it is undefined.

Both K&R 1 and 2 say that the behavior is undefined (p 50 and 53-54
respectively, I know 'em by heart) as does ANSI.

With respect to the gcc versus vcc code difference: note that gcc
produced more efficient code by evaluating in a different order.  This
is precisely the reason K&R give for leaving the order undefined.

Happy hacking,

jim