是否取消引用一个等于nullptr标准的未定义行为的指针?

pep*_*ico 9 c c++ language-lawyer

一位博客作者提出了有关空指针解除引用的讨论:

我在这里提出一些反驳论点:

他引用标准的主要推理理由是:

当'podhd'是空指针时,'&podhd-> line6'表达式在C语言中是未定义的行为.

C99标准说明了以下关于'&'地址的运算符(6.5.3.2"地址和间接运算符"):

一元&运算符的操作数应该是函数指示符,[]或一元*运算符的结果,或者是一个左值,它指定一个不是位字段的对象,并且不用寄存器存储类说明符声明.

表达式'podhd-> line6'显然不是函数指示符,是[]或*运算符的结果.这是一个左值表达式.但是,当'podhd'指针为NULL时,表达式不指定对象,因为6.3.2.3"Pointers"表示:

如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较.

当"左值在评估时未指定对象时,行为未定义"(C99 6.3.2.1"左值,数组和函数指示符"):

左值是具有对象类型或除void之外的不完整类型的表达式; 如果左值在评估时未指定对象,则行为未定义.

所以,同样的想法简要说明:

当在指针上执行 - >时,它会计算到没有对象存在的左值,因此行为是未定义的.

这个问题纯粹是基于语言的,我不会问一个给定的系统是否允许用任何语言篡改地址0的内容.

据我所知,取消引用一个值等于的指针变量没有限制nullptr,甚至认为指针与nullptr(或(void *) 0)常量的比较在某些情况下可能会因为所述段落而在优化中消失,但这看起来像另一个问题是,它不会阻止取消引用其值等于的指针nullptr.请注意,我已经检查了其他SO问题和答案,我特别喜欢这组引用,以及上面的标准引号,我没有偶然发现一些明显从标准中推断出如果指针ptr比较等于nullptr,取消引用这将是未定义的行为.

我得到的最多是将常量(或其转换为任何指针类型)引用的是UB,但没有任何关于变量等于从中得到的值的变量nullptr.

我想清楚地将nullptr常量与保持值等于它的指针变量分开.但解决这两种情况的答案都是理想的.

我确实意识到,当进行比较nullptr等时,优化可以快速进行,并且可以简单地基于此来剥离代码.

如果结论是,如果ptr等于nullptr解除引用的值肯定是UB,另一个问题如下:

C和C++标准是否意味着地址空间中的特殊值必须仅存在才能表示空指针的值?

oua*_*uah 11

当你引用C时,解除引用空指针显然是来自此标准引用的未定义行为(强调我的):

(C11,6.5.3.2p4)"如果为指针分配了无效值,则unary*运算符的行为未定义 .102)"

102):"unary*运算符取消引用指针的无效值是空指针,地址与指向的对象类型不一致,以及对象在其生命周期结束后的地址."

C99中的相同引用与C89/C90中的相似.


Blo*_*lob 6

C++

\n\n

dcl.ref/5。

\n\n
\n

不应存在​​对引用的引用、引用数组和指向引用的指针。引用的声明应包含初始值设定项 (8.5.3),除非声明包含显式 extern 说明符 (7.1.1)、是类定义中的类成员 (9.2) 声明,或者是声明\n 参数或返回类型(8.3.5);见 3.1。应初始化引用以引用有效的对象或函数。[ 注意:特别是,空引用不能存在于明确定义的程序中,因为创建此类引用的唯一方法是将其绑定到由通过空指针间接,\n 这会导致未定义的行为。如 9.6 中所述,引用不能直接绑定到位字段。\n \xe2\x80\x94 尾注]

\n
\n\n

该注释很有趣,因为它明确表示取消引用空指针是未定义的。

\n\n

我确信它在其他更相关的上下文中说过,但这已经足够好了。

\n

  • 注释不规范;从这个注释中不能推断出取消引用空指针会导致 UB (8认同)
  • @pepper_chico [给你。](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232) “**2003 年 10 月会议的笔记:** [.. .] 我们一致认为标准中的方法似乎没问题:`p = 0; *p;` 本质上并不是一个错误。左值到右值的转换会给它带来未定义的行为。” (2认同)