C++ 创建的指针是否超过非一元运算符派生的非数组指针的末尾&;C+中未定义的行为+;17?

C++ 创建的指针是否超过非一元运算符派生的非数组指针的末尾&;C+中未定义的行为+;17?,c++,arrays,pointers,language-lawyer,c++17,C++,Arrays,Pointers,Language Lawyer,C++17,C++17标准似乎规定,如果指针指向数组元素,或者作为特殊例外,指针是一元运算符&的结果,则只能将整数添加到指针: 8.5.6[expr.add]描述对指针的添加: 将具有整数类型的表达式添加到指针或从指针中减去时,结果具有指针操作数的类型。如果表达式P指向具有n个元素的数组对象的元素x[i],则表达式P+J和J+P(其中J的值为J)指向(可能是假设的)元素x[i+J],如果0≤ i+j≤ n否则,行为未定义 此引文包括一个脚注: 为此,非数组元素的对象被视为属于单个元素数组见8.5.2.1 其

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

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

将具有整数类型的表达式添加到指针或从指针中减去时,结果具有指针操作数的类型。如果表达式P指向具有n个元素的数组对象的元素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类型元素的数组

非规范性脚注似乎有点误导,因为它引用的部分描述了一元运算符
&
结果的特定行为。似乎不允许将其他指针(例如来自非数组的新指针)视为单元素数组

这似乎表明:

void f(int a) {
    int* z = (new int) + 1; // undefined behavior
    int* w = &a + 1; // ok
}
这是对C++17所做更改的疏忽吗?我错过什么了吗?是否有理由只为一元运算符
提供“单元素数组规则”


注意:如标题中所述,此问题特定于C++17。C标准和C++标准的先前版本包含了不再存在的明确规范语言。像这样较老的模糊问题是不相关的。

是的,这似乎是标准中的一个缺陷

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!
这太荒谬了

8.5.2.1[表达式一元运算] […]如果一个对象不是数组元素,而其地址是以这种方式获取的,则该对象被视为属于具有一个T类型元素的数组


一旦被8.5.2.1“祝福”,对象就是一个元素数组。如果你不通过调用
&
至少一次来祝福它,那么它就从来没有被8.5.2.1祝福过,也不是一个元素数组。

“非规范性脚注似乎有点误导性”,这就是非规范性符号的作用。他们用通俗易懂的英语解释了其他地方更详细的东西。“是否有理由只为一元运算符提供“单元素数组规则”&?”是否有理由为其他对象提供该规则?@NicolBolas如果您使用
new
分配单个对象,您仍然有一个指向单个对象的指针,而不使用
&
,正如OP所提到的。问题是这条规则是否也适用于这种情况(或相关情况)。对我来说,这似乎是一个疏忽,因为根据定义
p==&*p
。嗯,我个人将8.5.2.1解释为:如果我们以这种方式接受地址,那么我们就。。。没有明确提到else,所以状态仍然是开放的。8.5.6概括了脚注中的内容,将单元素数组规则扩展到else情况。规范扩展——参见@ N.M.的评论……相关:每一个C或C++标准遵循C89的传统,期望编译器编写者认识到在标准的某些部分定义了某类动作的行为的情况下,其他部分称重叠的一般动作类别调用UB,如果没有合理的理由不这样做,则应按照规定的方式处理这两类行为。认识到这一点的编译器编写者不需要标准通过划分所有豁免使第二类规范复杂化,而那些不需要标准的编写者不太可能……生产出高质量的编译器,即使标准划分出所有需要的豁免。如果这些标准被解释为设计的,那么这些标准未能从确定UB的一般类别的规则中划出每一项豁免,将不会是一个缺陷