取消引用一个指向数组类型的结束指针

Dereferencing one past the end pointer to array type

在 C++ 中是否明确定义了对数组类型的尾数指针的引用?

考虑以下代码:

#include <cassert>
#include <iterator>

int main()
{
    // An array of ints
    int my_array[] = { 1, 2, 3 };

    // Pointer to the array
    using array_ptr_t = int(*)[3];
    array_ptr_t my_array_ptr = &my_array;

    // Pointer one-past-the-end of the array
    array_ptr_t my_past_end = my_array_ptr + 1;

    // Is this valid?
    auto is_this_valid = *my_past_end;

    // Seems to yield one-past-the-end of my_array
    assert(is_this_valid == std::end(my_array));
}

常识是取消引用最后一个指针是未定义的行为。但是,这是否适用于指向数组类型的指针?

这应该是有效的似乎是合理的,因为 *my_past_end 可以纯粹用指针算法解决并产生指向数组中第一个元素的指针, 是在那里,这恰好也是原始数组 my_array.

的有效尾数 int*

然而,另一种看待它的方式是 *my_past_end 正在生成对不存在的数组的引用,它隐式转换为 int*。该参考对我来说似乎有问题。

对于上下文,我的问题是由 , specifically the comments to 提出的。

编辑:这个问题不是 Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not? 的重复问题我在问问题中解释的规则是否也适用于指向数组类型的指针。

编辑 2:删除了 auto 以明确 my_array_ptr 不是 int*

这是CWG 232。这个问题可能看起来主要是关于取消引用一个空指针,但它从根本上是关于简单地取消引用不指向对象的东西意味着什么。关于这种情况没有明确的语言规则。

问题中的示例之一是:

Similarly, dereferencing a pointer to the end of an array should be allowed as long as the value is not used:

char a[10];
char *b = &a[10];   // equivalent to "char *b = &*(a+10);"

Both cases come up often enough in real code that they should be allowed.

这与 OP(上述表达式的 a[10] 部分)基本相同,除了使用 char 而不是数组类型。

Common wisdom is that it's undefined behavior to dereference a one-past-the-end pointer. However, does this hold true for pointers to array types?

根据指针的类型,规则没有区别。 my_past_end 是一个尾后指针,因此是否要取消引用它与 UB 无关,因为它指向一个数组而不是任何其他类型的类型。


虽然 is_this_valid 的类型 int*int(&)[3] (数组到指针衰减)初始化,因此这里没有任何内容实际上是从内存中读取的 - 即对语言规则的工作方式无关紧要。 my_past_end 是一个指针,其值为 past the end of an object,这是唯一重要的事情。

我相信它的定义很明确,因为它不会取消引用最后一个指针。

auto is_this_valid = *my_past_end;

my_past_endint(*)[3] 类型(指向包含 3 个 int 元素的数组的指针)。因此,表达式 *my_past_end 属于 int[3] 类型——因此与此上下文中的任何数组表达式一样,它 "decays" 指向类型 int* 的指针,指向初始 (第零个)数组对象的元素。这个 "decay" 是一个编译时操作。所以初始化简单地初始化 is_this_valid,一个 int* 类型的指针,指向刚好超过 my_array 的结尾。没有访问数组对象末尾的内存。