From: jimad@microsoft.com (Jim Adcock)
Subject: Re: Pointer comparisons
Date: 17 Dec 92 22:49:59 GMT
Organization: Microsoft Corporation

In article <BzDs2x.wA@frumious.uucp> uunet.ca!frumious!pat writes:
|"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".

It means the compiler *will* accept code containing pointer comparisons
as specified.

|"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?

The meaning of "address space" is *as given in the specification.*
IE the wording about the ordering of objects in an array, and members
within a common declaration section.  The meaning of "address space" as
defined by a conforming implementation need not be the same meaning of
"address space" as implemented by the underlying CPU.  A simple example
of this is the case of a C++ implementation targeting a P-code machine
which in turn has a software-implemented virtual address scheme.  
Yes people do write such implementation machines.  "Address
Space" in this case refers to the *implementation* address space, not
the *CPU* address space.  This in turn says its the *implementation* not
the CPU that defines the meaning of these things.  The implementation simply
has to implement its address space so that it meets the stated requirements
of the standard.  Another [weaker] example of this is a 486 CPU which 
can have a 48-bit virtual address space, but has *implementations* running
assuming one or more cases [possibly within one program] of the following
*implementation* models: 0:16, 2x0:16, 16:16, 0:32, 16:32, and 16+32.

If any implementation memory model meets the explicit requirements of
the language specification, then such *is* the meaning of "address space".

|"If two pointers point to elements of the same array ...".
|What if they point to members of elements?

Then you are allowed to *make* the comparison, but the *results* of the
comparison are *implementation defined* since the results of such a
comparison are not otherwise called out in the spec.

|   struct X { int a; int b; };
|   X x[2];
|
|Must it be true that &x[0].a < &x[1].a?  

Nope.

What about &x[0].b < &x[1].a?

Nope.

The specification makes no such requirement, thus there is no such
requirement.

|3) The relational operators define a total ordering on the set of
|   pointers of each type.  (All the normal rules, including
|   transitivity.)

Not reasonable for all the reasons already discussed.

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

Such a compiler would not be useful on implementations requiring
the segment identifier change.

|If we ignore the question of how much existing code this would
|break, is this a reasonable suggestion?

No, because you would be ignoring the question of how much existing
code this would break.  Including system implementations.

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

"Normal" depends very much on what one is used to.  You expectations
appear very "unnormal" to me. 

Code that depends on implementation details of address implementation
has repeatedly proven to be very fragile in the past.  Let's not get
sucked into depending on details of address implementaion again.  Let's
give ourselves the freedom to run optimally on whatever machine appear
today and in the future.