有效指针的含义

7
回答的评论中,我偶然看到了有关“有效指针”的讨论。由于我认为这一点通常很有趣:
在C++中,“有效指针”是什么?
具体而言: reinterpret_cast<const void*>(0x1)是有效指针吗?

也许如果你以编译时常量传播为重点重新阅读其他帖子,这可能会有所帮助,这是“constexpr”旨在解决的重大问题之一。 - Kerrek SB
1个回答

10

标准将实现分为两个一般类别:

  • 具有严格指针安全性的实现
  • 具有放宽指针安全性的实现

您的表达式绝对不是一个安全派生指针,因此在第一种情况下是无效的。

引用自3.7.4.3:

一个实现可能具有放宽指针安全性,在这种情况下,指针值的有效性不取决于它是否是安全派生的指针值。或者,实现可能具有严格的指针安全性,在这种情况下,如果指向具有动态存储期的对象的指针值不是安全派生的指针值,则该指针值是无效的指针值,除非引用的完整对象已被声明为可达(20.7.4)。【注:使用无效的指针值(包括将其传递给解分配函数)的效果是未定义的,请参阅3.7.4.2。即使不安全派生的指针值可能与某些安全派生的指针值相等,这也是正确的。 - 结束说明】不管实现是否具有放宽或严格的指针安全性,都是由实现定义的。

对于具有放宽安全性的实现,指针值如何获取并不重要,只要满足以下条件(3.9.2):

对象指针类型的有效值表示内存中字节的地址(1.7)或空指针。

0x1 在您的系统上是否为有效的内存地址? 对于某些嵌入式系统来说是的。 对于大多数使用虚拟内存的操作系统,从零开始的页面被保留为无效页面。


1
我不确定那是否为正确类型的引用。 "指针安全" 的内容是关于支持不透明垃圾收集,我认为。我的观点关于有效指针是各种“表达式”规则的结果,例如,您可以添加、减去和取消引用什么。 - Kerrek SB
@KerrekSB:指针值可以是有效的,但如果以某些方式使用,则仍可能导致未定义的行为(例如:将自动变量的地址传递给::operator delete())。 - Ben Voigt
关于您的编辑:这有点混淆,因为问题是关于constexpr指针的,而constexpr明确禁止具有未定义行为的表达式(例如越界数组访问)。因此,虽然您可能能够使用平台定义的重新解释地址,但它不允许作为常量表达式...(尽管我想我们知道这一点)。 - Kerrek SB
1
@KerrekSB:什么未定义行为?它已经被正确地对齐,而且还没有被取消引用。 - Ben Voigt
这并不是因为任何未定义的行为,而是由于使用了reinterpret_cast,所以它不是一个合法的常量表达式。 - Ben Voigt
我表达不够清楚 - 我想说的是你无法静态地证明它不是未定义行为。你甚至不能证明p + 0不是未定义行为。它可能没问题,但你无法知道(从语言内部)。如果在你的平台上没问题,那就是你引入的外部信息。 - Kerrek SB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接