Title
Pointer equality
Status
tc1
Section
7.6.10 [expr.eq]
Submitter
Nathan Myers

Created on 1998-11-13.00:00:00 last changed 255 months ago

Messages

Date: 2000-10-15.00:00:00

Proposed Resolution (10/00):

  • In 6.8.4 [basic.compound] paragraph 3, add the following wording immediately preceding, "The value representation of pointer types is implementation-defined":
    A valid value of an object pointer type represents either the address of a byte in memory (6.7.1 [intro.memory]) or a null pointer (7.3.12 [conv.ptr]). If an object of type T is located at an address A, a pointer of type cv T* whose value is the address A is said to point to that object, regardless of how the value was obtained. [Note: for instance, the address one past the end of an array (7.6.6 [expr.add]) would be considered to point to an unrelated object of the array's element type that might be located at that address.]
  • In 7.6.10 [expr.eq] paragraph 1, change the sentence beginning, "Two pointers of the same type..." to read:
    Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address (6.8.4 [basic.compound]).

(See also paper J16/00-0011 = WG21 N1234.)

Date: 2004-09-10.00:00:00

Nathan Myers: In 7.6.10 [expr.eq] , we have:

Pointers to objects or functions of the same type (after pointer conversions) can be compared for equality. Two pointers of the same type compare equal if and only if they are both null, both point to the same object or function, or both point one past the end of the same array.
What does this say, when we have
    int i[1];
    int j[1];
about the expression (i+1 == j) ? It seems to require padding between i[0] and j[0] so that the comparison will come out false.

I think this may be a defect, in that the quoted paragraph extends operator=='s domain too far beyond operator<'s. It should permit (but not require) an off-the-end pointer to compare equal to another object, but not to any element of the same array.

Mike Miller: I think this is reading more into the statement in 7.6.10 [expr.eq] paragraph 1 than is actually there. What does it mean for a pointer to "point to" an object? I can't find anything that definitively says that i+1 cannot "point to" j[0] (although it's obviously not required to do so). If i+1 is allowed to "point to" j[0], then i+1==j is allowed to be true, and there's no defect. There are places where aliasing is forbidden, but the N+1th element of an array doesn't appear to be one of them.

To put it another way, "points to" is undefined in the Standard. The only definition I can think of that encompasses the possible ways in which a pointer can get its value (e.g., the implementation-defined conversion of an arbitrary integer value to a pointer) is that it means "having the same value representation as would be produced by applying the (builtin) & operator to an lvalue expression designating that object". In other words, if the bits are right, it doesn't matter how you produced the value, as long as you didn't perform any operations that have undefined results. The expression i+1 is not undefined, so if the bits of i+1 are the same as those of &j[0], then i+1 "points to" j[0] and i+i==j is allowed to be true.

Tom MacDonald: C9X contains the following words for the "==" operator:

Two pointers compare equal if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
Matt Austern: I don't think there's anything wrong with saying that the result of
    int x[1];
    int y[1];
    std::cout << (y == x + 1) << std::endl;
is implementation defined, or even that it's undefined.

Mike Miller: A similar question could be raised about different objects that (sequentially) share the same storage. Consider the following:

    struct B {
        virtual void f();
    };
    struct D1: B { };
    struct D2: B { };
    void g() {
        B* bp1 = new D1;
        B* bp2 = new (bp1) D2;
        bp1 == bp2; // ???
    }
Section 6.7.3 [basic.life] paragraph 5 does not list this kind of comparison among the pointer operations that cause undefined behavior, so presumably the comparison is allowed. However, 7.6.10 [expr.eq] paragraph 1 describes pointer comparison in terms of "[pointing] to the same object," which bp1 and bp2 clearly do not do. How should we describe the result of this comparison?

Jason Merrill: When you consider comparing pointers to void, this seems to suggest that no two objects can have the same address, depending on your interpretation of "point to the same object." This would cripple the empty base optimization.

6.8.4 [basic.compound] refers to 'pointers to void or objects or functions'. In that case, 7.6.10 [expr.eq] does not allow you to compare them; it only allows comparing pointers to objects and functions.

History
Date User Action Args
2003-04-25 00:00:00adminsetstatus: dr -> tc1
2000-11-18 00:00:00adminsetstatus: ready -> dr
2000-05-21 00:00:00adminsetstatus: drafting -> ready
1999-09-14 00:00:00adminsetmessages: + msg95
1998-11-13 00:00:00admincreate