Article View: comp.std.c++
Article #1274Pointer comparisons
From: Patrick Smith
Date: Thu, 17 Dec 1992 01:56
Date: Thu, 17 Dec 1992 01:56
162 lines
6892 bytes
6892 bytes
(I hope nobody minds my changing the subject line to something
a little more succinct.)
While responding to a previous posting, I looked up what the
draft C++ standard (the September 17 version) had to say about
pointer comparisons. Here's an extract from section 5.9:
Pointers to objects or functions of the same type (after pointer
conversions) may be compared; the result depends on the relative
positions of the pointed-to objects or functions in the address
space.
Two pointers to the same object compare equal. If two pointers
point to nonstatic data members of the same object, the pointer
to the later declared member compares higher provided the two
members [are] not separated by an access-specifier label (11.1)
and provided their class is not a union. If two pointers
point to nonstatic members of the same object separated by an
access-specifier label (11.1) the result is unspecified.
If two pointers point to data members of the same union, they
compare equal (after conversion to void*, if necessary).
If two pointers point to elements of the same array or one beyond
the end of the array, the pointer to the object with the higher
subscript compares higher. Other pointer comparisons are
implementation dependent.
Unfortunately, my copy of the C standard isn't at all handy, so
I can't compare with what it says.
Some of this is quite unclear to me.
"Pointers ... may be compared". Does this mean any pair of pointers
may be compared, or some pairs may be compared? It certainly suggests
"any pair" to me, but some might interpret it as "some pairs".
"the result depends on the relative positions ... in the address
space." What does this mean? Must one convert the pointers into
actual addresses and return the result of comparing those addresses?
Probably not, given that "[o]ther pointer comparisons are
implementation dependent." Maybe one is to convert the pointers
into addresses and apply some (arbitrary) function to those addresses?
If so, why would one want such a condition? What happens if there's
more than one address space? This clause seems reasonable to me if
interpreted as "the general intent of pointer comparison is to compare
addresses", but perhaps it's not suitable as part of the specification
of the language.
"If two pointers point to elements of the same array ...".
What if they point to members of elements?
struct X { int a; int b; };
X x[2];
Must it be true that &x[0].a < &x[1].a? What about &x[0].b < &x[1].a?
"If two pointers point to data members of the same union, they compare
equal (after conversion to void*, if necessary)." This one seems
clear enough, but may have a trap for the unwary.
class A {};
class B {};
class C : public A, public B {};
union D {
B b;
C c;
} d;
Here the comparison &d.c == &d.b is legal, but might return 0
(it compares pointers to d.b and the B part of d.c). To compare
pointers to d.c and d.b themselves, one should explicitly cast
to void*. Ouch.
Let me try to be constructive for a change. Would something
similar to the following be reasonable? (It would clearly need
much more careful wording and attention to details.)
1) Any two pointers to the same type may be compared, with any of
the relational operators.
2) In general, the results of the comparisons need not have anything
to do with the objects to which the pointers point. For example,
it is possible that p and q point to the same object, but p != q.
(But see below.)
3) The relational operators define a total ordering on the set of
pointers of each type. (All the normal rules, including
transitivity.)
4) If two pointers p and q (of the same type) are obtained through
sequences of "normal" operations, then
p == q <==> p and q point to the same object
If p and q point to elements of the same array, or to
subobjects of _different_ elements of the same array,
then they compare the same way as the indexes of the
elements in the array.
As above when p and q point to members of the same (non-union)
object.
If p and q point to members of the same union object, then
p == q if either
- the members have the same type (ignoring const and volatile)
or
- p and q are void* pointers and were obtained by converting
directly from pointers to the types of the members, with
no intermediate conversions (again ignore const and
volatile everywhere).
If neither of these conditions is met, p == q is
implementation-defined.
For rule (4), "normal" operations would include things such as
the built-in & operator, adding integers to pointers to array
elements, normal casts (eg. derived class pointer to base class
pointer), and calls to standard library functions. It would
specifically exclude casts whose meaning is not defined by the
standard (eg. casting an integer to a pointer) and calling an
extern "C" function. (Actually, one could develop a notion of a
C function which only does "normal" operations and permit
calling such a function. (Is there already a concept of strictly
conforming C function, as opposed to program?))
On systems where a pointer can be treated as an integer address,
this should pose no problems.
On systems where a pointer is composed of a segment identifier
and an offset, the compiler might arrange that the "normal"
operations would never change the segment identifier.
Comparisons could then be done by just comparing the
segment identifier and offset. If two pointers to the same object
have different segment identifiers, then the programmer must have
applied some un"normal" operation, so it's OK if the pointers
compare unequal.
One might add a library function sameObject(p,q) which would
indicate whether p and q point to the same object, no matter
how p and q were obtained.
If we ignore the question of how much existing code this would
break, is this a reasonable suggestion?
And how much existing code would this break (that isn't already
broken)? Note that it doesn't break any code that restricts
itself to "normal" operations.
--
Patrick Smith
uunet.ca!frumious!pat
pat%frumious.uucp@uunet.ca
Technical Details
Message-ID:
<BzDs2x.wA@frumious.uucp>Path:
arc1-ca.pugleaf.net!sparky!uunet!elroy.jpl.nasa.gov!usc!zaphod.mps.ohio-state.edu!uunet.ca!frumious!patReferences:
<1992Dec9.191606.5665@lucid.com> <BzCG7K.2sG@frumious.uucp> <1992Dec16.202711.22367@bcrka451.bnr.ca>Show Full Headers
Complete Article Headers
Newsgroups: comp.std.c++ Path: arc1-ca.pugleaf.net!sparky!uunet!elroy.jpl.nasa.gov!usc!zaphod.mps.ohio-state.edu!uunet.ca!frumious!pat From: pat@frumious.uucp (Patrick Smith) Subject: Pointer comparisons Message-ID: <BzDs2x.wA@frumious.uucp> Date: Thu, 17 Dec 1992 01:56:56 GMT Reply-To: uunet.ca!frumious!pat References: <1992Dec9.191606.5665@lucid.com> <BzCG7K.2sG@frumious.uucp> <1992Dec16.202711.22367@bcrka451.bnr.ca> Organization: None Lines: 162