是否创建了一个超出非数组指针结尾的指针,该指针不是从C++ 17中的一元运算符和未定义行为派生的?

0x5*_*9df 14 c++ arrays pointers language-lawyer c++17

C++ 17标准似乎说如果指针指向数组元素,则只能将一个整数添加到指针中,或者,作为特殊异常,指针是一元运算符的结果&:

8.5.6 [expr.add]描述对指针的添加:

当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型.如果表达式P指向具有n个元素的数组对象 x的元素x [i] ,则表达式P + J和J + P(其中J具有值j)指向(可能是假设的)元素x [i + j]如果0≤i+j≤n; 否则,行为未定义.

该引言包括一个非规范的脚注:

为此目的,不是数组元素的对象被认为属于单元素数组; 见8.5.2.1

引用8.5.2.1 [expr.unary.op]讨论一元运算&符:

一元&运算符的结果是指向其操作数的指针...出于指针运算(8.5.6)和比较(8.5.9,8.5.10)的目的,一个不是数据元素的对象,其地址被采用以这种方式被认为属于具有T类型的一个元素的数组.

非规范性脚注似乎有些误导,因为它引用的部分描述了一元运算符结果的特定行为&.似乎没有任何东西允许其他指针(例如来自非数组new)被认为是单元素数组.

这似乎表明:

void f(int a) {
    int* z = (new int) + 1; // undefined behavior
    int* w = &a + 1; // ok
}
Run Code Online (Sandbox Code Playgroud)

这是对C++ 17所做更改的疏忽吗?我错过了什么吗?是否有理由认为"单元素数组规则"仅针对一元运算符提供&

注意:如标题中所述,此问题特定于C++ 17.C标准和C++标准的早期版本包含不再存在的明确的规范性语言.像这样的老问题模糊不清楚.

Yak*_*ont 6

是的,这似乎是标准中的一个错误.

int* z = (new int)+1; // undefined behavior.
int* a = new int;
int* b = a+1; // undefined behavior, same reason as `z`
&*a; // seeming noop, but magically makes `*a` into an array of one element!
int* c = a+1; // defined behavior!
Run Code Online (Sandbox Code Playgroud)

这太荒谬了.

8.5.2.1 [expr.unary.op]

[...]不是以这种方式获取地址的数组元素的对象被认为属于具有T类型的一个元素的数组

一旦被8.5.2.1"祝福",该对象就是一个元素的数组.如果你没有通过&至少调用一次来祝福它,它从未被8.5.2.1祝福并且不是一个元素的数组.

  • 已修复 https://github.com/cplusplus/draft/pull/3485/commits/ec295895ee06264dd62922332cfa49f71f0b181a (2认同)