James said:
Kenneth Brody wrote:
...
Yes.
Before anyone jumps on that answer, let me point out that while it's
basically true, there are some fuzzy issues. The fundamental problem is
that there are at least two kinds of pointers that a strictly conforming
program can legally use, but cannot legally dereference. Therefore,
it's not meaningfully guaranteed that they point at any location, and a
conforming implementation of C could implement them in a way that
renders the question "where does that pointer point?" meaningless. The
standard handles these as special cases.
The first kind is null pointers. All null pointers compare equal to each
other, and unequal to any pointer to an object.
The second kind of such pointers are the ones that are one element past
the end of an array. For this purpose, non-array objects count as
one-element arrays. A pointer one past the end of array compares equal
to any other pointer one past the end of the same array, and unequal to
any pointer to any other element of the same array. The standard permits
a pointer one past the end of one array to compare equal to a pointer to
the beginning of another array; this allows the obvious implementation
of pointers on most platforms, without requiring that there be unused
padding at the end of each object.
If you think of all null pointers as pointing at the same unusable
location, and all pointers one past the end of an a array as pointing at
a location which is where the next element of the array would go, if it
were one element larger, then all these special case rules become
obvious; they're just examples of the general rule that pointers compare
equal if and only if they point at the same memory location. However,
since you can't legally de-reference these pointers, the standard does
not require that the "thinking" I described in the first sentence of
this paragraph is true. That's why the standard handles them as special
cases.
Real world example: I remember one implementation of C for a
segment-offset architecture, where all pointers with an offset of 0 were
treated as null pointers, regardless of the segment value. It was very
meaningful on that platform to talk about where the null pointer
pointed: if the address it contained were passed to assembly language
code, it would access a very specific byte in memory, and it would be a
different byte for different null pointers. However, all null pointers
compared equal to each other, as required by the C standard, despite the
fact that they pointed at different locations. This wasn't a fully
conforming implementation of C, but the way it handled null pointers
wasn't one of it's areas of non-conformance.