【问题标题】:What pointer values are well-defined to compute? [duplicate]哪些指针值是明确定义的计算? [复制]
【发布时间】:2020-04-18 21:29:05
【问题描述】:

我的印象是,虽然取消引用不指向有效对象的指针是 UB,但简单地计算这样的指针就可以了。

但是,如果我对 expr.add[4] 的理解正确,则情况并非如此。

那么这些指针计算中哪些是明确定义的?

int a = 42;
int *p = &a;
p;           // valid, and obviously ok
p++;         // invalid, but ok, because one past the end of 'array' containing 1 element?
p++;         // UB ?

这个案子怎么样?

int *p = nullptr;
p;                // invalid, and obviously ok (considered one past the end?)
p++;              // one past the end? or UB?

【问题讨论】:

  • 在有效指针之外,唯一允许的 2 个指针是空指针和 1 个超出数组结尾。您的链接部分似乎清楚地总结了它?
  • @rustyx 对于第一种情况来说已经足够清楚了,我认为。不过我不确定第二种情况。
  • @rustyx 查看链接页面底部的注释 (76)
  • @RichardCritten 这就是我对第一个p++ 的推理。这不适用于第三种情况吗?
  • 你称之为“无效”的两种情况都是有效的。 Past-the-end 和空指针是有效指针。 (参见 [basic.compound]/3)

标签: c++ pointers language-lawyer


【解决方案1】:

在您的第一个示例中,第一个 p++ 定义明确,因为非数组被视为单长度数组。

这是相关的报价 (basic.compound/3.4):

出于指针算术 ([expr.add]) 和比较 ([expr.rel], [expr.eq]) 的目的,超过 n 个元素的数组 x 的最后一个元素末尾的指针被认为是等价于指向 x 的假设数组元素 n 的指针,并且 不是数组元素的 T 类型对象被认为属于具有一个 T 类型元素的数组

p++p 之后,它将指向(假设的)数组的最后一个(也是唯一一个)元素,这是明确定义的。它不是“无效,但可以”,因为指向对象末尾的指针不是无效指针,basic.compound/3.2

指针类型的每个值都是以下之一:

  • [...]

  • 一个指向对象末尾的指针

  • [...]

  • 一个无效的指针值。

第一个例子的第二个p++是UB,因为结果会指向假设的(&a)[1]元素之后,这个元素没有定义。

在您的第二个示例中,p++ 是 UB,因为只能将 0 添加到 nullptr (expr.add/4.1):

  • 如果 P 求值为 空指针值且 J 求值为 0,则结果为空指针值。

  • [...]

  • 否则,行为未定义

【讨论】:

  • 谢谢!非常有用的信息。
猜你喜欢
  • 2023-01-28
  • 2012-11-01
  • 2015-10-03
  • 2012-07-17
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 2020-05-25
相关资源
最近更新 更多