[net.lang.c] What is the difference

tom (04/28/83)

Concerning recent query why #2 below does not accomplish the same as #1.

1)
	if ( ! ((*p >= '0' && *p <= '9') ||
		(tolower(*p) >= 'a' && tolower(*p) <= 'f')) )
			return(0);
	p++;

2)
	if ( ! ((*p >= '0' && *p <= '9') ||
		(tolower(*p) >= 'a' && tolower(*p++) <= 'f')) )
			return(0);

It has to do with the proper evaluation of the logical OR(||) in #2.
if "*p" is a digit, the first paranthesized test evaluates TRUE.  Therefore,
since the expression "TRUE OR x" is always TRUE, there is no reason to do
the second parenthesized test.  The result of the OR is TRUE, the NOT(!)
is FALSE, so the entire test is FALSE and execution drops down to the
next statment without ever doing the "p++".  See pg 191 of "The C
Programming Language":

    "Unlike |, || guarantees left-to-right evaluation; moreover,
    the second operand is not evaluated if the value of the first
    operand is non-zero."

It was then asked how to rewrite #1 or #2 to eliminate the separate "p++"
statement of #1.  Why the h--- bother? Isn't the code sufficiently difficult
to read without hiding the incrementation?  For efficiency?
At best, avoiding the separate "p++" buys so little efficiency I doubt
it could ever be measured.  At worst, machines without an auto-post-
decrement instruction might be slower if the increment were bundled
into an earlier reference to "p".  And then of course, there is the
inefficiency of doing the "p++" immediately prior to returning,

Also, I think any solution which eliminates the separate "p++" would also
eliminate the logical optimization mentioned above -- namely all of the
comparisons would be done even though the result is known part-way through,
thus making it even less efficient.

- Tom Beres
{seismo, we13, mcnc}!rlgvax!tom

and (05/13/83)

In c-language, logical expressions are evaluated only enough
to determine truth or falsity of the entire expression,
so the p++ in (2) may not be reached - regardless of the
ORDER of evaluation.

There are, at least, two solutions.

1) One is Coltoff's 1).  Why must the ++ be inside?

2) Shift the endpoints of the range of p so as to use ++p
in the first place it is used.  Thus it is always evaluated.
This may be tricky, and in the sense that one needs to be
certain of the order, may be harder.
For example, suppose the if-expression is a tautology and
always TRUE, and suppose the c-compiler were smart enough
to recognize that fact.  Then no part of the expression
would have to be evaluated.

Richard

guy@rlgvax.UUCP (05/25/83)

The System III "tolower" is a subroutine, not a macro, so it doesn't evaluate
its argument twice.  The manual page for the System V "tolower" is the
same, so I suspect it is also a subroutine.

		Guy Harris
		RLG Corporation
		{seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy

tihor@cmcl2.UUCP (06/07/83)

#R:ariel:-34000:cmcl2:15400003:000:164
cmcl2!tihor    Jun  6 22:04:00 1983

(Re: separate compilation) Actually the Ada Reference Manual in essence 
requires a compiler to support separate compilation to be a validatable
Ada (tm) compiler.