home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / std / cplus / 1821 < prev    next >
Encoding:
Text File  |  1992-12-16  |  6.6 KB  |  174 lines

  1. Newsgroups: comp.std.c++
  2. Path: sparky!uunet!elroy.jpl.nasa.gov!usc!zaphod.mps.ohio-state.edu!uunet.ca!frumious!pat
  3. From: pat@frumious.uucp (Patrick Smith)
  4. Subject: Pointer comparisons
  5. Message-ID: <BzDs2x.wA@frumious.uucp>
  6. Date: Thu, 17 Dec 1992 01:56:56 GMT
  7. Reply-To: uunet.ca!frumious!pat
  8. References: <1992Dec9.191606.5665@lucid.com> <BzCG7K.2sG@frumious.uucp> <1992Dec16.202711.22367@bcrka451.bnr.ca>
  9. Organization: None
  10. Lines: 162
  11.  
  12. (I hope nobody minds my changing the subject line to something
  13. a little more succinct.)
  14.  
  15. While responding to a previous posting, I looked up what the
  16. draft C++ standard (the September 17 version) had to say about
  17. pointer comparisons.  Here's an extract from section 5.9:
  18.  
  19.    Pointers to objects or functions of the same type (after pointer
  20.    conversions) may be compared; the result depends on the relative
  21.    positions of the pointed-to objects or functions in the address
  22.    space.
  23.  
  24.    Two pointers to the same object compare equal.  If two pointers
  25.    point to nonstatic data members of the same object, the pointer
  26.    to the later declared member compares higher provided the two
  27.    members [are] not separated by an access-specifier label (11.1)
  28.    and provided their class is not a union.  If two pointers
  29.    point to nonstatic members of the same object separated by an
  30.    access-specifier label (11.1) the result is unspecified.
  31.    If two pointers point to data members of the same union, they
  32.    compare equal (after conversion to void*, if necessary).
  33.    If two pointers point to elements of the same array or one beyond
  34.    the end of the array, the pointer to the object with the higher
  35.    subscript compares higher.  Other pointer comparisons are
  36.    implementation dependent.
  37.  
  38. Unfortunately, my copy of the C standard isn't at all handy, so
  39. I can't compare with what it says.
  40.  
  41. Some of this is quite unclear to me.
  42.  
  43.  
  44. "Pointers ... may be compared".  Does this mean any pair of pointers
  45. may be compared, or some pairs may be compared?  It certainly suggests
  46. "any pair" to me, but some might interpret it as "some pairs".
  47.  
  48.  
  49. "the result depends on the relative positions ... in the address
  50. space."  What does this mean?  Must one convert the pointers into
  51. actual addresses and return the result of comparing those addresses?
  52. Probably not, given that "[o]ther pointer comparisons are
  53. implementation dependent."  Maybe one is to convert the pointers
  54. into addresses and apply some (arbitrary) function to those addresses?
  55. If so, why would one want such a condition?  What happens if there's
  56. more than one address space?  This clause seems reasonable to me if
  57. interpreted as "the general intent of pointer comparison is to compare
  58. addresses", but perhaps it's not suitable as part of the specification
  59. of the language.
  60.  
  61.  
  62. "If two pointers point to elements of the same array ...".
  63. What if they point to members of elements?
  64.  
  65.    struct X { int a; int b; };
  66.    X x[2];
  67.  
  68. Must it be true that &x[0].a < &x[1].a?  What about &x[0].b < &x[1].a?
  69.  
  70.  
  71. "If two pointers point to data members of the same union, they compare
  72. equal (after conversion to void*, if necessary)."  This one seems
  73. clear enough, but may have a trap for the unwary.
  74.  
  75.    class A {};
  76.    class B {};
  77.    class C : public A, public B {};
  78.    union D {
  79.       B b;
  80.       C c;
  81.    } d;
  82.  
  83. Here the comparison &d.c == &d.b is legal, but might return 0
  84. (it compares pointers to d.b and the B part of d.c).  To compare
  85. pointers to d.c and d.b themselves, one should explicitly cast
  86. to void*.  Ouch.
  87.  
  88.  
  89. Let me try to be constructive for a change.  Would something
  90. similar to the following be reasonable?  (It would clearly need
  91. much more careful wording and attention to details.)
  92.  
  93. 1) Any two pointers to the same type may be compared, with any of
  94.    the relational operators.
  95.  
  96. 2) In general, the results of the comparisons need not have anything
  97.    to do with the objects to which the pointers point.  For example,
  98.    it is possible that p and q point to the same object, but p != q.
  99.    (But see below.)
  100.  
  101. 3) The relational operators define a total ordering on the set of
  102.    pointers of each type.  (All the normal rules, including
  103.    transitivity.)
  104.  
  105. 4) If two pointers p and q (of the same type) are obtained through
  106.    sequences of "normal" operations, then
  107.  
  108.       p == q   <==>   p and q point to the same object
  109.  
  110.       If p and q point to elements of the same array, or to
  111.       subobjects of _different_ elements of the same array,
  112.       then they compare the same way as the indexes of the
  113.       elements in the array.
  114.  
  115.       As above when p and q point to members of the same (non-union)
  116.       object.
  117.  
  118.       If p and q point to members of the same union object, then
  119.       p == q if either
  120.  
  121.          - the members have the same type (ignoring const and volatile)
  122.  
  123.       or
  124.  
  125.          - p and q are void* pointers and were obtained by converting
  126.            directly from pointers to the types of the members, with
  127.            no intermediate conversions (again ignore const and
  128.            volatile everywhere).
  129.  
  130.       If neither of these conditions is met, p == q is
  131.       implementation-defined.
  132.  
  133.  
  134. For rule (4), "normal" operations would include things such as
  135. the built-in & operator, adding integers to pointers to array
  136. elements, normal casts (eg. derived class pointer to base class
  137. pointer), and calls to standard library functions.  It would
  138. specifically exclude casts whose meaning is not defined by the
  139. standard (eg. casting an integer to a pointer) and calling an
  140. extern "C" function.  (Actually, one could develop a notion of a
  141. C function which only does "normal" operations and permit
  142. calling such a function.  (Is there already a concept of strictly
  143. conforming C function, as opposed to program?))
  144.  
  145.  
  146. On systems where a pointer can be treated as an integer address,
  147. this should pose no problems.
  148.  
  149. On systems where a pointer is composed of a segment identifier
  150. and an offset, the compiler might arrange that the "normal"
  151. operations would never change the segment identifier.
  152. Comparisons could then be done by just comparing the
  153. segment identifier and offset.  If two pointers to the same object
  154. have different segment identifiers, then the programmer must have
  155. applied some un"normal" operation, so it's OK if the pointers
  156. compare unequal.
  157.  
  158. One might add a library function sameObject(p,q) which would
  159. indicate whether p and q point to the same object, no matter
  160. how p and q were obtained.
  161.  
  162.  
  163. If we ignore the question of how much existing code this would
  164. break, is this a reasonable suggestion?
  165.  
  166. And how much existing code would this break (that isn't already
  167. broken)?  Note that it doesn't break any code that restricts
  168. itself to "normal" operations.
  169.  
  170. -- 
  171. Patrick Smith
  172. uunet.ca!frumious!pat
  173. pat%frumious.uucp@uunet.ca
  174.