创建一个指针超过非数组指针的末尾,而非一元运算符& C ++ 17中未定义的行为?

时间:2018-06-18 18:40:42

标签: c++ arrays pointers language-lawyer c++17

C ++ 17标准似乎说只有当指针指向数组元素时,才能将整数添加到指针,或者,作为特殊异常,指针是一元运算符{{1}的结果}:

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

  

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

此引用包括non-normative脚注:

  

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

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

  

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

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

这似乎表明:

new

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

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

1 个答案:

答案 0 :(得分: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!

这太荒谬了。

8.5.2.1 [expr.unary.op]

  

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

一旦受8.5.2.1的“祝福”,对象就是一个元素组成的数组。如果您没有通过至少一次调用&来祝福它,那么它永远不会被8.5.2.1祝福,并且不是一个元素的数组。