代码之家  ›  专栏  ›  技术社区  ›  Peter - Reinstate Monica

p>nullptr:未定义的行为?

  •  1
  • Peter - Reinstate Monica  · 技术社区  · 3 年前

    以下用于空指针检查的有缺陷的代码使用某些编译器进行编译,但不使用其他编译器(请参阅 godbolt ):

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

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

    该比较编译为

    • 11.1之前的gcc
    • MSVC 19最新版本为/std:c++17,但不支持/std:c++20。

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

    更新的gcc产生的错误(“指针与整数零的有序比较('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)。是否(4.3), “两个指针都不需要”, 意味着行为未定义,代码无效?相比之下,2012年的标准包含了5.9/2中的措辞“[…]如果[两个相同类型的p和q指针]中只有一个为空,则结果 的p<q、 p>q、 p<=q、 并且p>=q是 未指明。"


    1. 措辞似乎不正确。 nullptr_t 如果我正确阅读标准,它不是一个积分类型。

    1 回复  |  直到 3 年前
        1
  •  8
  •   Eric M Schmidt    3 年前

    7.6.9规定,“对操作数执行左值到右值([conv.val])、数组到指针([conw.array])和函数到指针([conv.func])的标准转换……转换后的操作数应具有算术、枚举或指针类型。”

    指定的转换都不适用于文字 nullptr 。此外,它不具有算术、枚举或指针类型。因此,这种比较是不合理的。