Is it undefined behaviour in C++ to access elements in adjacent arrays as in following code?
#include <type_traits>
#include <algorithm>
#include <iterator>
int main()
{
int a[10][10];
static_assert(std::is_standard_layout< decltype(a) >::value, "!");
std::fill(std::begin(*std::begin(a)), std::end(*std::prev(std::end(a))), 0);
struct B { int b[10]; };
B b[10];
static_assert(std::is_standard_layout< decltype(b) >::value, "!");
std::fill(std::begin(std::begin(b)->b), std::end(std::prev(std::end(b))->b), 0);
}
Technically I think for POD-types it is legal to access underlying memory in any manner one want, but what about std::*
stuff?
What if I change all begin/end
to rbegin/rend
?
Yes, this is UB.
From [basic.compound]:
Every value of pointer type is one of the following:
- a pointer to an object or function (the pointer is said to point to the object or function), or
- a pointer past the end of an object ([expr.add]), or
- the null pointer value ([conv.ptr]) for that type, or
- an invalid pointer value.
A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively. [ Note: A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type that might be located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see [basic.stc]. — end note ]
And [expr.add]/4:
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements,86 the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i+j] if 0≤i+j≤n; otherwise, the behavior is undefined. Likewise, the expression P - J points to the (possibly-hypothetical) element x[i−j] if 0≤i−j≤n ; otherwise, the behavior is undefined.
So &a[0][0] + 10
is a "pointer past the end of an object", it's the past the end pointer of the first array. You cannot add one more to that pointer - there is no defined behavior for this case.
A pointer cannot be both a "past the end" pointer and a "pointer to object" (interpreting &a[0][0] + 10
as if it were &a[1][0]
). It's one or the other.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With