Paul Schlie wrote:
(as an aside, as most target implementations treat pointers as unsigned
values, its not clear that presuming signed integer overflow semantics are
a reasonable choice for pointer comparison optimization)
The point is not of presuming signed integer overflow semantics (I was
corrected on this by Ian Taylor). It is of presuming that pointers never
move before the beginning of their object. If you have an array of 20
elements, pointers &a[0] to &a[20] are valid (accessing &a[20] is not valid),
but the compiler can assume that the program does not refer to &a[-2].

Paolo

Yes (and in which case if the compiler is smart enough to recognize
this it should generate an error, not emit arbitrary [or absents] of
code); but the example in question was:

void f(char *buf)  {
 unsigned int len = 0xFFFFFF00u; /* or similar */

if (buf+len < buf) puts("true");

}

In which case buf is merely a pointer which may point to any char, not a
char within a particular array, implying buf+len is also just a pointer,
ultimately being compared against buf;

nope, that may be in your mind what C means, but it's not what the
C language says. A pointer can only point within the allocated
object. Given that constraint, it is obvious that the condition can
never be true. Of course if the compiler elides the test on this
basis, it is nice if it warns you (certainly there is no basis
for an error message in the above code).

If all such pointers are presumed to be restricted to pointing to the
element they were originally assigned, then all composite pointer arithmetic
such as buf+len would be invalid.

no, that's just wrong, the computation buf+len is valild if the resulting pointer is within the original object, a condition that
cannot be caught statically, and with typical implementations
cannot be caught dynamically in all cases either.

You might want to think of an implementation of C where pointers are
a pair, a base pointer and an offset, and pointer arithmetic only
works on the offset. This is a valid implementation, and is in some
sense the formal semantic model of C. It is used in some debugging
versions of C that always check this condition at run time.

It was also used in effect on the 286, where pointers at the
hardware level are segment+offset, and it is valid in C on the
286 to do arithmetic only on the offset part of the address,
and there were indeed C compilers that worked this way.

Alex Stepanov told me once that he preferred Ada to C, because Ada
has proper pointer arithmetic (via the type Integer_Address) which
is defined to work in Ada in the manner that Paul mistakenly expects
for C. Integer_Address would be a bit of a pain to implement on
a 286 :-)

Of course in C in practice, pointers are just machine addresses,
and more general pointer arithmetic does "work", but any program
taking advantage of this is not written in the C language.



All this being said, I understand that in
general this is an anomalous case, however on small embedded machines with
small memory spaces or when writing drivers or memory allocators, such
pointer arithmetic may be perfectly legitimate it would seem.


Reply via email to