use of if (!cptr) and if (cptr) && a programming error

Andrew Koenig ark at alice.UUCP
Sat Jul 22 15:01:48 AEST 1989


In article <2990 at nmtsun.nmt.edu>, dwho at nmtsun.nmt.edu (David Olix) writes:
> [Skipping all the "In article..." stuff]
> >[Material everybody has seen n times deleted.]
> >I am kind of butting in [ :-) ], but how 'bout
> >        while ( ( myptr = my_func() )->x != myptr->y )
> >                {
> >                }
> 
> >THAT WILL NOT WORK! [...]
> 
> Actually, "Mastering C" by Craig Bolon, SYBEX Inc., p. 273 says that
> parenthesis operators have the HIGHEST priority, therefore what's inside
> (myptr = my_func()) would get evaluated first.  Also, it specifies that
> grouping for the '!=' operator is from left to right.  Now, the author of
> this book may have been wrong....  Anyone seen an "official" statement
> from K&R?

I might as well put my two cents in.

Precedence and order of evaluation are two different things.

Precedence has to do with deciding what sub-expression is the
operand of each operator.  For example, the precedence rules of
C say that

	a != b != c

is equivalent to

	(a != b) != c

and is not equivalent to

	a != (b != c)

However, nowhere does C make any guarantee about the order in
which a, b, and c will be fetched.  It is completely legal for
a C compiler to evaluate

	a != b != c

by the following sequence of operations:

	copy b into register 1
	copy c into register 2
	copy a into register 3
	compare registers 1 and 3 and put the result into register 0
	compare registers 0 and 2

Similarly, in the expression

	( myptr = my_func() )->x != myptr->y
	
there is no doubt that the two things being compared are

	( myptr = my_func() )->x

and

	myptr->y

However, the compiler is under no obligation to evaluate these
two sub-expressions in any particular sequence.  Only in the case
of && || , and ?: operators does the compiler incur any such
obligation.  Thus, this expression could be rewritten:

	( ( myptr = my_func() ), ( myptr->x != myptr->y ) )

to guarantee that the value of `myptr' used in the comparison
would always be that returned by my_func().  Moreover, the
precedence rules (not order of evaluation) allow the expression
to be simplified slightly:

	( myptr = my_func(), myptr->x != myptr->y )

with precisely the same effect.

Finally, note that commas that separate function arguments
are not comma operators.  In this expression:

	my_other_func ( myptr = my_func(), myptr->x != myptr->y )

there is no guarantee of whether myptr is assigned before or
after it is used to fetch the values of myptr->x and myptr->y.
For such a guarantee, one would have to write

	myptr = my_func(), my_other_func ( myptr, myptr->x != myptr->y )
-- 
				--Andrew Koenig
				  ark at europa.att.com



More information about the Comp.lang.c mailing list