[comp.lang.c] Testing Equal Pointers

msb@sq.com (Mark Brader) (03/28/89)

> ... from comp.lang.c ...
> > It is possible however to have two pointers point to the same storage
> > location but which compare unequal.
> 
> Why is this dismal situation reflected in the pANS?  How can standard C
> let pointers to the same object compare unequal?  ...  STANDARD C
> PROVIDES NO WAY at all to tell if two pointers point to the same object!

Wrong (in pANS, "standard", C), no matter how loud you shout.  (I've added
a cross-posting back to comp.lang.c to point out that the compiler(s) referred
to in the original article would not be complying to the pANS in this respect.
Followups are directed to comp.lang.c also, since this article should close
the topic from a pANS viewpoint!)

The wording here did undergo some late editorial changes and may be
different between the October draft and the final December version of the
proposed standard.  Also, note that the discussion of equality is partly
under relational operators, rather than equality operators.  This is simply
because the presentation (in order of precedence) happens to get to them first.
Equality affects the relational operators too because the two expressions

		a <= b && !(a < b)
	and
		a == b

are equivalent in the absence of undefined behavior.

From Section 3.3.8 "Relational operators", page 50, lines 7-10:

#  If two pointers to object or incomplete types both point to the same
#  object, or both point one past the last element of the same array
#  object, they compare equal.  If two pointers to object or incomplete
#  types compare equal, both point to the same object, or both point
#  one past the last element of the same array object.

There is a footnote about invalid prior operations and undefined behavior.

Then, in Section 3.3.9 "Equality operators", page 50, lines 28-36:

#  [These] operators are analogous to the relational operators except
#  for their lower precedence.  Where the operands have types and values
#  suitable for the relational operators, the semantics detailed in
#  Section 3.3.8 apply.
#
#  If two pointers to object or incomplete types are both null pointers,
#  they compare equal.  If two pointers to object or incomplete types
#  compare equal, they both are null pointers, or both point to the same
#  object, or both point one past the last element of the same array
#  object.  If two pointers to function types compare equal, either both
#  are null pointers, or both point to the same function.  If two pointers
#  to function types compare equal, either both are null pointers, or
#  both point to the same function.

There is a footnote which is redundant.

Mark Brader, SoftQuad Inc., Toronto, utzoo!sq!msb, msb@sq.com
	A standard is established on sure bases, not capriciously but with
	the surety of something intentional and of a logic controlled by
	analysis and experiment. ... A standard is necessary for order
	in human effort.				-- Le Corbusier

chip@ateng.ateng.com (Chip Salzenberg) (03/29/89)

Unfortunately, I apparently did not make myself clear when writing about
pointer comparison under Microsoft C.  Prescott Turner misunderstood me,
posting his expressions of disbelief.  For reference, I wrote in part:

> For totally correct comparisons of all pointers, it's necessary
> to normalize them by hand, or be sure that they are cast to "huge *" when
> any pointer arithmetic is done.  Otherwise, the different combinations of
> segment+offset that actually refer to the same address do not compare equal.

In the context of the quoted article, "all pointers" includes pointers
constructed *by hand*, i.e. non-portably.  If all pointers in a Microsoft C
program are generated in the normal C fashion, that is, by use of the "&"
operator and pointer arithmetic, the "==" and "!=" operators work as
expected.  No need to worry, Prescott.

Incidentally, these comments apply equally to Turbo C.

On the other hand, Doug Gwyn comments:

>(Except that certain operations not permitted of conforming applications
>might produce pointers that accidentally refer to the same location; but
>since that would be totally erroneous code, you shouldn't worry about it.)

I beg to disagree.  Non-portable is not the same as erroneous, at least in
the real world of applications programming.  (I'm sure Doug knows what I
mean here, even if he avoids such situations wherever possible, as I do.)

After all, if a given algorithm is non-portable and is therefore surrounded
by "#ifdef MSDOS"/"#endif", why bother trying to make its implementation
portable?

For an example:  Name a portable way to get the complete shift state of a
keyboard.  No, wait, that's too hard.  Name a portable way to *express* the
complete shift state of a keyboard.  Code involving such an entity is non-
portable from the get-go; so there's no reason to avoid non-portable coding
in its implementation.
-- 
Chip Salzenberg             <chip@ateng.com> or <uunet!ateng!chip>
A T Engineering             Me?  Speak for my company?  Surely you jest!
	  "It's no good.  They're tapping the lines."