p > nullptr:未定义的行为?



以下有缺陷的空指针检查代码可以在某些编译器中编译,但不能在其他编译器中编译(参见godbolt):

bool f()
{
char c;
return &c > nullptr;
}

令人反感的部分是指针与nullptr之间的关系比较。

比较用

编译
  • gcc before 11.1
  • MSVC 19。最新的/std:c++17,但不支持/std:c++20。

但是没有clang版本(我检查到4.0)编译它。

更新的gccs产生的错误(' 'char*'和'std::nullptr_t')">1与clang('无效操作数到二进制表达式('char*'和'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)显然不适用于这里,剩下(4.3)。 意味着行为未定义,代码无效?相比之下,2012年的标准包含了5.9/2 "[…]如果[两个相同类型的指针p和q]中只有一个为空,则结果为术;q, p> q,术中;= q, p> = q不明!">


1措辞似乎不正确。如果我没看错标准的话,nullptr_t不是整型。

7.6.9 states, "在操作数. ....上执行左值到右值([conv.lval])、数组到指针([conv.array])和函数到指针([conv.func])的标准转换转换后的操作数必须为算术、枚举或指针类型。">

所有指定的转换都不适用于文字nullptr。此外,它没有算术、枚举或指针类型。因此,比较是病态的。

最新更新