I'm trying to understand the following snippet from CPP reference. Can someone explain in a little more detail why x2[1]
is unreachable from source
? Can't we reach it via &x2[0][0] + 10
for example?
int x2[2][10];
auto p2 = std::launder(reinterpret_cast<int(*)[10]>(&x2[0][0]));
// Undefined behavior: x2[1] would be reachable through the resulting pointer to x2[0]
// but is not reachable from the source
The reachability condition basically asks whether it is possible to access a given byte of memory via pointer arithmetic and
reinterpret_cast
from a given pointer. The technical definition, which is effectively the same, is given on the linked cppreference page:x2
is an array of 2 arrays of10
arrays ofint
. Let's suppose we call the two arraysa
andb
.&x2[0][0]
is anint*
pointing to the first element ofa
.&x2[0][0] + 10
is anint*
pointer one-past the last elementa
. The address of this pointer value is also the address at whichb
begins. However one cannot obtain a pointer tob
or one of its elements viareinterpret_cast
since&x2[0][0] + 10
doesn't point to any object that is pointer-interconvertible withb
or one of its elements.In terms of the technical definition, the only object pointer-interconvertible with the first element of
a
is the object itself. Therefore the reachable bytes from a pointer to the first element ofa
are only the bytes ofa
, which is the array immediately enclosing this object.Therefore the reachable bytes through
&x2[0][0]
are only those of the arraya
, not includingb
. E.g.*(&x2[0][0] + 10) = 123;
has undefined behavior.However if
std::launder
were to return a pointer toa
(of typeint(*)[10]
), then(p2+1)[i]
would be a way to access all elements ofb
. Or in terms of the technical definition, the array immediately enclosing the objectp2
points to would bex2
, so that all bytes ofx2
are reachable.This means after the
std::launder
bytes that weren't reachable before would become reachable. Therefore the call has undefined behavior.