Pointer arithmetic and comparisons.

Chris Torek chris at mimsy.umd.edu
Wed Dec 13 17:06:48 AEST 1989


In article <232 at bohra.cpg.oz> ejp at bohra.cpg.oz (Esmond Pitt) writes:
>... you should test for <= &buffer[last-1], not < &buffer[last].

It makes no difference:
>	char *p = buffer;
>	char *e = &buffer[len-1];
>
>	while ((*p++ = getchar()) != EOF && p <= e) {

(For the moment, let us ignore the fact that *p==EOF might well never be
true.)  Chances are that if the loop

	for (p = base; p <= &base[SIZE - 1]; p++)

works, the loop

	for (p = base; p < &base[SIZE]; p++)

will also work.  In particular, the latter loop tends to fail when
base+SIZE `wraps around', as it were, to 0.  That is, &base[SIZE] is
very small, and hence (p < &base[SIZE]) is always false.

Suppose this is the case.  Now let p be &buf[SIZE - 1], and assume we
are working on the former loop (p <= &base[SIZE - 1]).  Then, if
arithmetic works `as expected', p++ will cause p to wrap around to zero,
and the next iteration will test a very small `p' against a large address
and the loop will continue.  That is, the loop will run forever, rather
than not at all.

The only time something useful happens is when &base[SIZE] is computed
in a different way than (&base[SIZE - 1]) + 1.  Any system that does
this is not compiling C code correctly.

The situation is almost exactly the same as the case of

	for i := 0 to maxint do ... od;

which must be coded in C as

	for (i = 0;; i++) {
		...
		if (i == INT_MAX) break;
	}

(or any equivalent).  The variable i must not be incremented when
it is INT_MAX, as the result can either be overflow or INT_MIN (e.g.,
from 32767 to -32768, or from 2147483647 to -2147483648).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list