From: Dann Corbit on
This fragment of code is from zlib:

/* We check for insufficient lookahead only every 8th comparison;
* the 256th check will be made at strstart+258.
*/
do {
} while(
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
scan < strend);


Now, the && operators are sequence points, so the behavior is not
undefined. Assuming that scan and match are not aliased, is the result
of all the side effects in the computation unspecified or not?

At first I thought it was unspecified, but since all the assignments are
identical I am pretty well convinced that the result is not unspecified,
but I thought it would be good to ask the experts.
From: Ben Bacarisse on
Dann Corbit <dcorbit(a)connx.com> writes:

> This fragment of code is from zlib:
>
> /* We check for insufficient lookahead only every 8th comparison;
> * the 256th check will be made at strstart+258.
> */
> do {
> } while(
> *++scan == *++match && *++scan == *++match &&
> *++scan == *++match && *++scan == *++match &&
> *++scan == *++match && *++scan == *++match &&
> *++scan == *++match && *++scan == *++match &&
> scan < strend);
>
>
> Now, the && operators are sequence points, so the behavior is not
> undefined.

I'm happy to take your word for it (you know the rest of the code) but
from the fragment above the &&s do not, on their own, stop this being
undefined (in the C sense of the word). This being c.u.p there may be
other standards and/or assurances that the code relies on.

> Assuming that scan and match are not aliased, is the result
> of all the side effects in the computation unspecified or not?

There are some things in the code that are "unspecified behaviour" as
defined by C (for example the order of evaluation of some of the side
expressions) but I'm not sure that is the sort of unspecified you
mean.

Using the C meaning, I don't see any scope for anything being
unspecified in the results of the increments.

> At first I thought it was unspecified, but since all the assignments are
> identical I am pretty well convinced that the result is not unspecified,
> but I thought it would be good to ask the experts.

--
Ben.
From: Peter Nilsson on
Dann Corbit <dcor...(a)connx.com> wrote:
> This fragment of code is from zlib:
>
> /* We check for insufficient lookahead only every 8th
> * comparison; the 256th check will be made at
> * strstart+258.
>  */
> do {

[I presume there's more code here, otherwise a plain while
loop would make more sense.]

> } while(
>       *++scan == *++match && *++scan == *++match &&
>       *++scan == *++match && *++scan == *++match &&
>       *++scan == *++match && *++scan == *++match &&
>       *++scan == *++match && *++scan == *++match &&
>       scan < strend);
>
> Now, the && operators are sequence points, so the behavior
> is not undefined. Assuming that scan and match are not
> aliased, is the result of all the side effects in the
> computation unspecified or not?

But match and scan can't be aliased unless there's macro
play afoot. If they themselves alias, i.e. point to the
same address, then there's still no harm reading that
address twice and doing a comparison. The test, i == i
is fine for most types [NANs aside.]

> At first I thought it was unspecified, but since all the
> assignments are identical

The pointers match and scan are assigned (incremented)
independantly. Unless they're the same object (which
would require some macro play,) there's no harm incrementing
each just once prior to a sequence point.

Whenever the increment actually occurs is incidental since
the result of ++x must yield the value of x + 1 (converted
to the type of x.)

> I am pretty well convinced that the result is not
> unspecified, but I thought it would be good to ask
> the experts.

Then comp.lang.c is more obvious place to ask! ;)

But it's difficult to know which aspect of this code you
think is unspecified. None of the comparisons can be
determined until runtime, and how many comparisons are
made before one fails can also only be determined at
runtime. But unless scan and match are pointers to
types with trap representations then the result of the
comparisons should be well defined.

The code does presume that strend is a multiple of 8
ahead of scan. If that's not the case, then scan may
run past the end of a buffer. Which would render the
behaviour undefined.

Are you talking about the case where scan and match
are character pointers and comparison of 'random'
extraneous (but present) bytes are made? If the pointers
are unsigned char pointers, then the read values will
indeed be unspecified if not previously assigned, but
still usable in comparison, although the comparison may
yield unintended (unspecified) results. If they are
signed character pointers, then it is theoretically
undefined if the implementation has trap representations
for signed character types.

The code does seem strange in the sense that it pre-
increments scan but is compared strictly less than
against strend.[ As if doing 'for (x = 1; x < 10;...'
rather than 'for (x = 0; x < 10;...' or
'for (x = 1; x <= 10;...' which are more idiomatic.
But then as I said, there's probably stuff inside
the loop body which would make this make sense.

Lastly, strend is okay as a 'variable' but is, at the
very least, reserved for use as an external identifier.
Identifiers begining str[a-z] are generally best avoided
in C.

--
Peter