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_castfrom a given pointer. The technical definition, which is effectively the same, is given on the linked cppreference page:x2is an array of 2 arrays of10arrays ofint. Let's suppose we call the two arraysaandb.&x2[0][0]is anint*pointing to the first element ofa.&x2[0][0] + 10is anint*pointer one-past the last elementa. The address of this pointer value is also the address at whichbbegins. However one cannot obtain a pointer tobor one of its elements viareinterpret_castsince&x2[0][0] + 10doesn't point to any object that is pointer-interconvertible withbor one of its elements.In terms of the technical definition, the only object pointer-interconvertible with the first element of
ais the object itself. Therefore the reachable bytes from a pointer to the first element ofaare 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::launderwere 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 objectp2points to would bex2, so that all bytes ofx2are reachable.This means after the
std::launderbytes that weren't reachable before would become reachable. Therefore the call has undefined behavior.