`reinterpret_cast`是一个'T *`到'T(*)[N]`是不确定的行为?

时间:2018-01-25 13:28:19

标签: c++ language-lawyer reinterpret-cast strict-aliasing c++17

考虑以下情况:

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有效?

2 个答案:

答案 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之间。