p > nullptr:未定义的行为?

Pet*_*ica 1 c++ pointers comparison-operators nullptr c++20

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

\n
bool f()\n{\n    char c;\n    return &c > nullptr;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

攻击性的部分是指针 和 之间的关系比较nullptr

\n

比较编译为

\n
    \n
  • 11.1 之前的 gcc
  • \n
  • MSVC 19.latest 使用 /std:c++17,但不使用 /std:c++20。
  • \n
\n

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

\n

较新的 gcc 产生的错误 (“有序比较指针与整数零 (\'char*\' 和 \'std::nullptr_t\')” 1与 clang 中的错误有点不同 (“二进制表达式的无效操作数 ( \'char *\' 和 \'std::nullptr_t\')")。

\n

C++20 ISO 标准在 7.6.9/3ff 中规定了应用于指针的关系运算符:

\n
\n

如果两个操作数都是指针,则执行指针转换 (7.3.12) [...] 以将它们\n转换为复合指针类型 (7.2.2)。转换后,操作数应具有相同的类型。

\n

比较不同对象指针的结果是根据符合以下规则的偏序来定义的:

\n(4.1) \xe2\x80\x94 如果两个指针指向同一数组的不同元素,或其子对象,指向下标较高的元素的指针需要比较较大。
\n(4.2) \xe2\x80\x94 如果两个指针指向同一对象的不同非静态数据成员,或者指向此类成员的子对象,则递归地要求指向后来声明的成员的指针比较更大,前提是两个成员具有相同的访问控制(11.9),两个成员都不是零大小的子对象,并且它们的类不是联合。
\n(4.3) \xe2\x80\x94 否则,不需要比较两个指针是否大于另一个。

\n
\n

(在此上下文中,“指向对象的指针”仅意味着该类型不是指向函数的指针,而不是指指针值引用实际对象。)

\n

(4.1) 和 (4.2) 显然不适用这里,只剩下 (4.3)。(4.3) “两个指针都不需要”是否意味着行为未定义,并且代码无效?相比之下,2012 年标准包含 5.9/2 中的措辞“[...]如果[相同类型 p 和 q 的两个指针]中只有一个为 null,则 p<q, p>q, p 的结果\n <=q 和 p>=q未指定。”

\n
\n

1措辞似乎不正确。nullptr_t如果我正确地阅读了标准,则不是整数类型。

\n

Eri*_*idt 8

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

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