以下有缺陷的空指针检查代码可以在某些编译器中编译,但不能在其他编译器中编译(参见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
。此外,它没有算术、枚举或指针类型。因此,比较是病态的。