c++ - 是否在非数组指针的末尾创建一个指针,该指针不是从 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;否则,行为是 undefined。
此引用包含一个非规范性脚注:
为此目的,一个不是数组元素的对象被认为属于一个单元素数组;见 8.5.2.1
其中引用了 8.5.2.1 [expr.unary.op] 讨论一元运算&
符:
一元 & 运算符的结果是指向其操作数的指针...对于指针算术 (8.5.6) 和比较 (8.5.9, 8.5.10),该对象不是采用其地址的数组元素这种方式被认为属于一个类型为 T 的元素的数组。
非规范脚注似乎有点误导,因为它引用的部分描述了特定于一元运算符结果的行为&
。似乎没有任何东西允许将其他指针(例如来自 non-array new
)视为单元素数组。
这似乎表明:
void f(int a) {
int* z = (new int) + 1; // undefined behavior
int* w = &a + 1; // ok
}
这是对 C++17 更改的疏忽吗?我错过了什么吗?是否有理由只为一元运算符提供“单元素数组规则” &
?
注意:如标题中所述,此问题特定于 C++17。C 标准和 C++ 标准的早期版本包含不再存在的清晰规范语言。像这样的较老的、模糊的问题是不相关的。
解决方案
是的,这似乎是c++17标准中的一个错误。
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 祝福过,并且不是一个元素的数组。
推荐阅读
- vue.js - Nuxt/axios 模块设置在方法中不起作用
- python - 当我尝试使用 SublimeREPL 运行 Python 脚本时,Sublime Text 3 显示 EOFError()
- google-chrome-extension - 测试使用 chrome 存储 API 的 chrome 扩展更新的最佳方法?
- html - 我的联系表格在切换到移动版本时会产生多余的边距
- c++ - BuildMacro 元素在 Visual Studio 属性和项目中的作用是什么?
- mysql - 在mysql中添加时间戳列
- android - 未调用数据库引用 valueEventListener
- java - Spring Boot Java 客户端无法连接到 Zeebe Docker
- docker - Xdebug 3 未在 docker 中连接
- sql - 如何检查一个日期是否小于另一个日期,如果返回一个结果