指针与nullptr进行关系比较是否属于未定义行为?
nullptr的关系比较兼容性问题 以下是一段存在缺陷的空指针检查代码,它能在部分编译器编译通过,但在另一些编译器下编译失败:
bool f() { char c; return &c > nullptr; }
问题核心在于指针与nullptr的关系比较。
编译通过的环境
- GCC 11.1版本之前
- 开启
/std:c++17的最新版MSVC 19,但开启/std:c++20时无法编译
编译失败的环境
所有版本的Clang(测试至4.0版本)均无法编译该代码。
编译器错误信息
- 新版GCC给出的错误信息:
ordered comparison of pointer with integer zero ('char*' and 'std::nullptr_t')¹ - Clang给出的错误信息:
invalid operands to binary expression ('char *' and 'std::nullptr_t')
标准条款分析
C++20 ISO标准7.6.9/3ff条款中关于指针关系运算符的规定如下:
若两个操作数均为指针,则执行指针转换(7.3.12)[...]以将它们转换为复合指针类型(7.2.2)。转换后,操作数必须具有相同类型。
比较指向对象的不相等指针的结果基于符合以下规则的偏序关系:
(4.1) — 若两个指针指向同一数组的不同元素或其子对象,则指向下标较大元素的指针必须被判定为更大。
(4.2) — 若两个指针指向同一对象的不同非静态数据成员或此类成员的子对象(递归地),则在两个成员具有相同访问控制(11.9)、均非零大小子对象且所属类不是联合体的前提下,指向后声明成员的指针必须被判定为更大。
(4.3) — 否则,无需判定任一指针大于另一指针。
(此处的“指向对象的指针”仅表示类型不是指向函数的指针,而非指针值指向实际对象。)
(4.1)和(4.2)显然不适用于&c > nullptr这个场景,仅剩下(4.3)。那么(4.3)中“无需判定任一指针大于另一指针”是否意味着行为未定义且代码无效?
相比之下,2012版标准5.9/2条款中的表述为:[...]若[两个相同类型的指针p和q]中仅有一个为空,则p<q、p>q、p<=q和p>=q的结果为**未指定值**。
¹ 该表述似乎并不准确。根据标准,nullptr_t并非整数类型。
内容的提问来源于stack exchange,提问作者Peter - Reinstate Monica

