Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!rutgers!dptg!ulysses!andante!alice!ark From: ark@alice.UUCP (Andrew Koenig) Newsgroups: comp.lang.c Subject: Re: use of if (!cptr) and if (cptr) && a programming error Message-ID: <9663@alice.UUCP> Date: 22 Jul 89 05:01:48 GMT References: <10099@mpx2.mpx.com> <93@microsoft.UUCP> <10100@mpx2.mpx.com> <2990@nmtsun.nmt.edu> Organization: AT&T Bell Laboratories, Liberty Corner NJ Lines: 90 In article <2990@nmtsun.nmt.edu>, dwho@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@europa.att.com