[comp.unix.questions] Evaluating autoincrements in function calls

welch%UMASS.BITNET@wiscvm.wisc.EDU (02/26/87)

Here's an interesting C error/mis-feature I'd like to bring to your
attention as a possible portability problem.
 
int    set[]={1,2,3},
    i = 0;
main()
{
printf("\nnumbers in set indexed by incr integer = %d,%d,%d",
    set[i++],
    set[i++],
    set[i++]);
 
printf("\nnumbers in set indexed by constants = %d,%d,%d,
    set[0],
    set[1],
    set[2]);
}
 
The lattice C (V2.15) compiler produces:
 
numbers in set indexed by incr integer = 1,2,3
numbers in set indexed by constants = 1,2,3
 
as output, while the Microsoft (V4.0) and VAX C (V2.2-015) compilers produce:
 
numbers in set indexed by incr integer = 3,2,1
numbers in set indexed by constants = 1,2,3
 
 
In the second case the compiler is evaluating the arguments to
the printf function right to left, including the autoincrement
instructions, as it builds the stack.
 
Lattice evaluates the autoincrement instructions left to
right before pushing the arguments in the function call on the stack
(from right to left).
 
I don't want to be swamped with replies as to which set of results
is correct but I would be interested to know if there is a standard
which documents the correct behavior of argument evaluation.
 
Jonathan Welch
 
Bitnet: jhwelch@amherst

mcvoy@uwvax.UUCP (02/26/87)

In article <4707@brl-adm.ARPA> welch%UMASS.BITNET@wiscvm.wisc.EDU writes:
->In the second case the compiler is evaluating the arguments to
->the printf function right to left, including the autoincrement
->instructions, as it builds the stack.
-> 
->I don't want to be swamped with replies as to which set of results
->is correct but I would be interested to know if there is a standard
->which documents the correct behavior of argument evaluation.

This is explicitly undefined in the K&R definition, in other words, you
may not depend on any order of evalualtion when considering function
parameters.  My guess is that it was done as a efficiency/favour
for/to compilers/{compiler writers}.  Functions are done a lot;
it would be ill-advised to slow them down by enforcing evaluation
orders here.  It is unfortunate, though.  Inconsistencies suck.
-- 
Larry McVoy 	        mcvoy@rsch.wisc.edu, 
      		        {seismo, topaz, harvard, ihnp4, etc}!uwvax!mcvoy

"They're coming soon!  Quad-stated guru-gates!"

chris@mimsy.UUCP (02/27/87)

>In article <4707@brl-adm.ARPA> welch%UMASS.BITNET@wiscvm.wisc.EDU writes:
>>int    set[]={1,2,3}, i = 0;
>main() {
>printf("\nnumbers in set indexed by incr integer = %d,%d,%d",
>    set[i++], set[i++], set[i++]);
 
[produces different results with different compilers].

In article <3279@rsch.WISC.EDU> mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) writes:
>This is explicitly undefined in the K&R definition,

And in the ANSI draft standard.

And then in an aside:

>It is unfortunate, though.  Inconsistencies suck.

What inconsistencies?  Those between different compilers?  One must
expect some.  What does the following program, written in ZIFP (zifp
is for pedantry :-) ) do when translated to your favourite Pascal-like
language?

	proc sighed returns program_status <- {
	    var i: integer <- 0;
	    // `set' is a reserved word in this imaginary language
	    var iset: array [integer: 0..2] of integer <- {1, 2, 3};
	    proc f returns integer <- {
		f <- iset[i];
		i <- i + 1;
	    }
	    print("numbers in set: ", f, f, f);
	    sighed <- success;
	}

-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu

black@ee.UCLA.EDU (02/27/87)

> numbers in set indexed by incr integer = 3,2,1
> numbers in set indexed by constants = 1,2,3

I recall having this happen once.  Actually, it never 'happened';
I caught it before it was a bug (in the larval stage, one could say :=)).
A pass from lint caught it and said, "Order of evaluation unspecified."

If you look at "The Bible" (K&R C), page 192, you will see that
the comma operator does not really apply to this case.  Furthermore,
K&R, page 50, states a case almost exactly like yours and concludes:
"...writing code which depends on order of evaluation is bad..."

Caveat hacker!

Rex Black

black@ee.ucla.edu                                          ARPA        
...!{ihnp4,ucbvax,sdcrdcf,trwspp}!ucla-cs!uclaee!black     UUCP

Disclaimer:  No offense intended.

mcvoy@uwvax.UUCP (02/28/87)

In article <5604@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
-In article <3279@rsch.WISC.EDU> I write:
->It is unfortunate, though.  Inconsistencies suck.
-
-What inconsistencies?  Those between different compilers?  One must
-expect some.  

Well, correct me if I am wrong, but there is nothing inherent in the
language that _forces_ function argument evaluation to have an undefined
order.  One _could_ state that it works left-to-right or odd numbered args
first, then even, whatever.  It's just more work for the compiler writer
and potentially more code at procedure call time.  I've never written a
production compiler but I have studied them and written toy ones and I
think that I could evaluate args in any order you wish.

Don't get me wrong, I'm not arguing that we should change it, I'm just
trying to point out that it IS an inconsistency and that IS annoying.  If
you don't believe that, consider the result if they had decided that
operator precedence should be undefined as well (no, not the order of A +
B + C, but the order of A + B * 3 / 4).  They could have done this, right?
As long as they provided parens to force one way or another.  But it would
have certainly violated the rule of least astonishment, as does the
function arg stuff...

Actually, it's more than annoying, it causes non-portable code.  C hackers
being what they are tend not to worry about this until it bites them
(yeah, I know that _you_ worry about it, but you are the exception, not
the norm, I'm afraid).  If you don't believe that, try porting BSD code to
a 16 bit int machine or a machine that does make *((char*)0) == 0.  Have
fun :-)
-- 
Larry McVoy 	        mcvoy@rsch.wisc.edu, 
      		        {seismo, topaz, harvard, ihnp4}!uwvax!mcvoy

"It's a joke, son! I say, I say, a Joke!!"  --Foghorn Leghorn

ken@rochester.UUCP (02/28/87)

|Don't get me wrong, I'm not arguing that we should change it, I'm just
|trying to point out that it IS an inconsistency and that IS annoying.  If

Sure it is an inconsistency, but the point is nobody promised a fixed
evaluation order. Are you going to complain too that different compilers
have different MAXREALs? Or that '\f' isn't always 014? C does run
on EBCDIC machines you know.

Programmers can't blithely ignore limitations.

	Ken