Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!seismo!brl-adm!adm!hoey@nrl-aic.arpa
From: hoey@nrl-aic.arpa (Dan Hoey)
Newsgroups: comp.lang.c
Subject: Re: conditional expression evaluation question
Message-ID: <2337@brl-adm.ARPA>
Date: Wed, 14-Jan-87 13:43:01 EST
Article-I.D.: brl-adm.2337
Posted: Wed Jan 14 13:43:01 1987
Date-Received: Thu, 15-Jan-87 00:44:09 EST
Sender: news@brl-adm.ARPA
Lines: 37


    From: "George M. Sipe" 
    Message-Id: <207@rebel.UUCP>
    Date: 12 Jan 87 21:40:40 GMT

    ... Does C guarantee execution of portions of a
    conditional expression, even when the result is known after partial
    evaluation?....

The semantics of the expression ``((*cp++ | *cp++ | *cp++) == 0)''
includes the side-effect of incrementing ``cp'' three times, and so
must be preserved by any correct optimizer.  Even if the optimizer, by
clever program analysis, could deduce that in some program ``cp'' was
already pointing to a block of zeroes, and so could optimize away the
entire test (or the entire loop), it would have to leave in the
increments.  I can't estimate the likelihood of someone writing an
opitimizer that is incorrect in this respect.

However, the language explicitly leaves the *order* of these
side-effects unspecified, except of course that each increment of
``cp'' must be preceded by the corresponding dereference.  However, the
optimizer is free to postpone all of the increments until after all the
dereferences, so you may end up executing something that acts like

	while (cp < end && triples < MINSKIP) {
		if ((*cp | *cp | *cp) == 0) ++triples;
		else triples = 0;
		cp += 3;
	}

which is not what you want.  I think the rewritten code is fine, though
I would tend to use cp[1] instead of *(cp+1), and I would also tend to
use a conditional-or (||) instead of logical-or (|) and
conditional-not (!) instead of a comparison (== 0).  But that's just
how I write.

Dan Hoey