This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


73. Pointer equality

Section: 7.6.10  [expr.eq]     Status: TC1     Submitter: Nathan Myers     Date: 13 Nov 1998

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.

Proposed Resolution (10/00):

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