From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: Pointer comparisons
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Fri, 18 Dec 1992 20:25:39 GMT

In article <BzDs2x.wA@frumious.uucp> uunet.ca!frumious!pat writes:
>(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".
>
	Seems to many 'any' to me.
>
>"the result depends on the relative positions ... in the address
>space."  What does this mean?  

	This means that the committee has committed a grave error.
Too many Unix people. The ARM also commits this error in
assuming the existence of *an* address space. The 386 has
8K address spaces per process. The idea that relative positioning
of pointers into different segments is meaningful is absurd.

>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.
>
	Agreed.
>
>"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?
>
	I would expect this, but it doesnt say so.
>
>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.

	Sure, why not?
>
>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.)

	Yes. It is implementation defined, except in special
circumstances.
>
>3) The relational operators define a total ordering on the set of
>   pointers of each type.  (All the normal rules, including
>   transitivity.)

	Accepted as axiom tentatively.

>
>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.

	Given we defer analysis of "normal" operations this
axiom may contradict axiom 4.

	On a linear address machine, 3 & 4 could be made to work,
so such a system can exist. On a segmented machine, 3 & 4 might
be mutually exclusive.
>
>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), 

	Dont forget the obvious ones: assignment and initialisation.

	Also, some casts might be dubious, espcially casts to/from
void*.

>and calls to standard library functions.  

	I have some doubts about this.

>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.  

	I think you would have to make ALL calls, even to
C++ functions problematic. Because a called extern C++ function
might do one of the excluded naughty casts.

	This doesnt matter though.

>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.

	This is more complicated than you think.
The 386 'selector' is bits which contain selector access
priviledges, as well as the bits relating to the
actual entry in the descriptor table.

	Furthermore, some system might mix 16 and 32 bit
segments (in fact all protected mode operating systems I 
know about allow this) and often have some way of
'interconverting' between them.

	Thus this requirement may be unimplementable.

>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.

	This may or may not be true on the 386  or other machines.
I suspect suitable restrictions on 'normal' might make
this workable.
>
>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.
>
	One might, but it had better not be required.
Because it may be unimplementable on some systems.
 
>
>If we ignore the question of how much existing code this would
>break, is this a reasonable suggestion?

	It is reasonable to start from this suggestion,
but you have to look at the fact that axiom 3 and axiom 4
might not be compatible. 
>
>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.
>

	You dont know that. How do you know that pointers
stored in one segment and those in another, BOTH pointing
to the same object dont have different layouts?

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Newsgroups: comp.std.c++