Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it undefined behavior to `reinterpret_cast` a `T*` to `T(*)[N]`?

Consider the following scenario:

std::array<int, 8> a;
auto p = reinterpret_cast<int(*)[8]>(a.data());
(*p)[0] = 42;

Is this undefined behavior? I think it is.

  • a.data() returns a int*, which is not the same as int(*)[8]

  • The type aliasing rules on cppreference seem to suggest that the reinterpret_cast is not valid

  • As a programmer, I know that the memory location pointed by a.data() is an array of 8 int objects

Is there any rule I am missing that makes this reinterpret_cast valid?

like image 802
Vittorio Romeo Avatar asked Sep 06 '25 08:09

Vittorio Romeo


2 Answers

An array object and its first element are not pointer-interconvertible*, so the result of the reinterpret_cast is a pointer of type "pointer to array of 8 int" whose value is "pointer to a[0]"1.In other words, despite the type, it does not actually point to any array object.

The code then applies the array-to-pointer conversion to the lvalue that resulted from dereferencing such a pointer (as a part of the indexing expression (*p)[0])2. That conversion's behavior is only specified when the lvalue actually refers to an array object3. Since the lvalue in this case does not, the behavior is undefined by omission4.


*If the question is "why is an array object and its first element not pointer-interconvertible?", it has already been asked: Pointer interconvertibility vs having the same address.

1See [expr.reinterpret.cast]/7, [conv.ptr]/2, [expr.static.cast]/13 and [basic.compound]/4.

2See [basic.lval]/6, [expr.sub] and [expr.add].

3[conv.array]: "The result is a pointer to the first element of the array."

4[defns.undefined]: undefined behavior is "behavior for which this document imposes no requirements", including "when this document omits any explicit definition of behavior".

like image 73
T.C. Avatar answered Sep 09 '25 17:09

T.C.


Yes the behaviour is undefined.

int* (the return type of a.data()) is a different type from int(*)[8], so you are breaking strict aliasing rules.

Naturally though (and this is more for the benefit of future readers),

int* p = a.data();

is perfectly valid, as is the ensuing expression p + n where the integral type n is between 0 and 8 inclusive.

like image 31
Bathsheba Avatar answered Sep 09 '25 17:09

Bathsheba