Pointer interconvertibility vs having the same address Pointer interconvertibility vs having the same address arrays arrays

Pointer interconvertibility vs having the same address


There are apparently existing implementations that optimize based on this. Consider:

struct A {    double x[4];    int n;};void g(double* p);int f() {    A a { {}, 42 };    g(&a.x[1]);    return a.n; // optimized to return 42;                // valid only if you can't validly obtain &a.n from &a.x[1]}

Given p = &a.x[1];, g might attempt to obtain access to a.n by reinterpret_cast<A*>(reinterpret_cast<double(*)[4]>(p - 1))->n. If the inner cast successfully yielded a pointer to a.x, then the outer cast will yield a pointer to a, giving the class member access defined behavior and thus outlawing the optimization.


More generally, what is the rationale for distinguishing the notion of pointer-interconvertibility from the notion of having the same address?

It is hard if not impossible to answer why certain decisions are made by the standard, but this is my take.

Logically, pointers points to objects, not addresses. Addresses are the value representations of pointers. The distinction is particularly important when reusing the space of an object containing const members

struct S {    const int i;};S s = {42};auto ps = &s;new (ps) S{420};foo(ps->i);  // UB, requires std::launder

That a pointer with the same value representation can be used as if it were the same pointer should be thought of as the special case instead of the other way round.

Practically, the standard tries to place as little restriction as possible on implementations. Pointer-interconvertibility is the condition that pointers may be reinterpret_cast and yield the correct result. Seeing as how reinterpret_cast is meant to be compiled into nothing, it also means the pointers share the same value representation. Since that places more restrictions on implementations, the condition won't be given without compelling reasons.


Because the comittee wants to make clear that an array is a low level concept an not a first class object: you cannot return an array nor assign to it for example. Pointer-interconvertibility is meant to be a concept between objects of same level: only standard layout classes or unions.

The concept is seldom used in the whole draft: in [expr.static.cast] where it appears as a special case, in [class.mem] where a note says that for standard layout classes, pointers an object and its first subobject are interconvertible, in [class.union] where pointers to the union and its non static data members are also declared interconvertible and in [ptr.launder].

That last occurence separates 2 use cases: either pointers are interconvertible, or one element is an array. This is stated in a remark and not in a note like it is in [basic.compound], so it makes it more clear that pointer-interconvertibility willingly does not concern arrays.