【发布时间】:2019-11-30 15:26:23
【问题描述】:
这是有效的 C++ 吗?
int main()
{
int i = 0;
int* pi = &i;
++pi;
}
我知道数组类型允许使用过去结束的指针,但在这种情况下我不确定。该代码在技术上是否具有未定义的行为?
【问题讨论】:
标签: c++ pointers language-lawyer pointer-arithmetic
这是有效的 C++ 吗?
int main()
{
int i = 0;
int* pi = &i;
++pi;
}
我知道数组类型允许使用过去结束的指针,但在这种情况下我不确定。该代码在技术上是否具有未定义的行为?
【问题讨论】:
标签: c++ pointers language-lawyer pointer-arithmetic
是的,没关系。它是任何指针类型可能包含的四类值之一。
[basic.compound](强调我的)
3每个指针类型的值都是以下之一:
- 指向对象或函数的指针(据说该指针指向对象或函数),或
- 超过对象末尾的指针 ([expr.add]),或
- 该类型的空指针值 ([conv.ptr]),或
- 一个无效的指针值。
一个指针类型的值,它是一个指向或超过一个指针结尾的指针 object 表示内存中第一个字节的地址 ([intro.memory]) 对象或内存中的第一个字节占用 结束后对象分别占用的存储空间。 [ 注意:超过对象末尾的指针 ([expr.add]) 不是 被认为指向对象类型的不相关对象 可能位于该地址。指针值在以下情况下变为无效 它表示的存储达到其存储期限的结束;看 [基本.stc]。 — 尾注 ] 用于指针算术 ([expr.add]) 和比较 ([expr.rel], [expr.eq]),指针过去 考虑 n 个元素的数组 x 的最后一个元素的结尾 等效于指向 x 的假设数组元素 n 的指针 一个不是数组元素的类型 T 的对象被认为是 属于具有一个 T 类型元素的数组。
如您所见,此处还提到了数组类型,它们的假设对象位于末尾。正如footnote in [expr.add] 解释的那样,获得一个过去指针的算法意味着也是有效的:
如 [basic.compound] 中所述,为此目的,非数组元素的对象被认为属于单元素数组,并且超过 n 个元素数组的最后一个元素的指针被认为是为此,它相当于一个指向假设数组元素 n 的指针。
【讨论】:
pi += 2 也可以吗?如果不是,为什么?
int a; int b; *(&a + 1) = 3; - 即使&a + 1 指向b,这仍然不是获取指向b 的指针的有效方法。