"reinterpret_cast"一个"T*"到"T(*)[N]&q

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

本文关键字:quot 一个 reinterpret cast      更新时间:2023-10-16

请考虑以下场景:

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

这是未定义的行为吗?我认为是的。

  • a.data()返回一个int*,这与int(*)[8]

  • cpp首选项上的类型别名规则似乎表明reinterpret_cast无效

  • 作为一名程序员,我知道a.data()指向的内存位置是8int对象的数组

我缺少什么规则使这个reinterpret_cast有效吗?

数组对象及其第一个元素不是指针可相互转换*的,因此reinterpret_cast的结果是"指向 8int数组的指针"类型的指针,其值是"指向a[0]的指针">1。换句话说,尽管有类型,它实际上并不指向任何数组对象。

然后,代码将数组到指针的转换应用于取消引用此类指针(作为索引表达式(*p)[0])2的一部分所产生的左值。仅当左值实际引用数组对象3时,才会指定该转换的行为。由于本例中的左值没有,因此行为未由省略4定义。


*如果问题是"为什么数组对象及其第一个元素不可指针互转换?",已经有人问过:指针可互换性与具有相同地址。

1参见[expr.reinterpret.cast]/7、[conv.ptr]/2、[expr.static.cast]/13和[basic.compound]/4。

2参见 [basic.lval]/6, [expr.sub] 和 [expr.add]。

3[conv.array]:"结果是指向数组第一个元素的指针。

4[defns.undefined]:未定义的行为是"本文档不强加任何要求的行为",包括"当本文档省略任何明确的行为定义时"。

是的,行为是未定义的。

int*(返回类型a.data())与int(*)[8]不同,因此您违反了严格的别名规则。

当然(这更有利于未来的读者),

int* p = a.data();

是完全有效的,随后的表达式p + n也是如此,其中整型n介于 0 和 8 之间(含 0 和 8)。