考虑以下情况:
std::array<int, 8> a;
auto p = reinterpret_cast<int(*)[8]>(a.data());
(*p)[0] = 42;
这是未定义的行为吗?我想是的。
a.data()
返回int*
,与int(*)[8]
cppreference 上的type aliasing rules似乎暗示reinterpret_cast
无效
作为程序员,我知道a.data()
指向的内存位置是8
int
个对象的数组
是否有任何我错过的规则使reinterpret_cast
有效?
答案 0 :(得分:12)
数组对象及其第一个元素不是指针可互换的 * ,因此reinterpret_cast
的结果是类型为&#34的指针;指向8 {{的数组的指针1}}&#34;其值为&#34;指向int
&#34; 1 的指针。换句话说,尽管有类型,它实际上并不指向任何数组对象。
然后,代码将数组到指针的转换应用于取消引用此类指针(作为索引表达式a[0]
) 2 的一部分而产生的左值。仅当左值实际引用数组对象 3 时才指定该转换的行为。由于这种情况下的左值没有,因此省略 4 的行为是不明确的。
* 如果问题是&#34;为什么数组对象及其第一个元素不是指针可互换的?&#34;,它已被问到:{{3 }} 子>
1 请参阅Pointer interconvertibility vs having the same address,[expr.reinterpret.cast]/7,[conv.ptr]/2和[expr.static.cast]/13。
2 请参阅[basic.compound]/4,[basic.lval]/6和[expr.sub]。
3 [expr.add]:&#34;结果是指向数组的第一个元素的指针。&#34; 子>
4 [conv.array]:未定义的行为是&#34;本文档没有要求的行为&#34;,包括&#34;当本文档省略任何明确的行为时行为的定义&#34;。
答案 1 :(得分:7)
是的,行为未定义。
int*
(a.data()
的返回类型)与int(*)[8]
的类型不同,因此您违反了严格的别名规则。
当然,(这更有利于未来的读者),
int* p = a.data();
完全有效,随后的表达式p + n
也是如此,其中整数类型n
介于0和8之间。