"is not required" == 未定义的行为?

"is not required" == undefined behavior?

我的问题主要是关于术语以及如何解释标准。

[expr.rel]#4:

The result of comparing unequal pointers to objects is defined in terms of a partial order consistent with the following rules:

(4.1) If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript is required to compare greater.

(4.2) If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided the two members have the same access control ([class.access]), neither member is a subobject of zero size, and their class is not a union.

(4.3) Otherwise, neither pointer is required to compare greater than the other.

我对如何解释 (4.3) 有点困惑。这是否意味着这个

#include <iostream>
int main() {
    int x;
    int y;
    std::cout << (&x < &y);
    std::cout << (&x < &y);
}

是...

?

换句话说,我知道 (4.3) 在这里适用,但我不确定其含义。当标准说“它可以是 A 或 B”时,这是否等同于说“它未定义”?

valid C++ code

是的。

标准在任何地方都没有说这是 UB 或格式不正确,而且这种情况也不缺少描述行为的规则,因为引用的 4.3 适用。

and the output is either 11 or 00

我不确定10或01在技术上保证不输出1.

鉴于两个指针都不需要比较大于另一个,比较的结果可以是真也可以是假。在这种情况下,对于相同操作数的每次调用,似乎没有明确要求结果相同。

1 但我认为这在实践中不太可能。我也认为保留这种可能性并不是故意的。相反,目的是允许确定性的,但不一定是完全有序的。


P.S.

auto comp = std::less<>;

std::cout << comp(&x, &y);
std::cout << comp(&x, &y);

将保证为 11 或 00,因为 std::less(与其朋友一样)保证对指针施加严格的总顺序。

对于提供的代码,这种情况适用:

(4.3) Otherwise, neither pointer is required to compare greater than the other.

没有提到UB,因此严格阅读“两者都不是必需的”表明每次评估的比较结果都可能不同。

这意味着该程序可以有效地输出以下任何结果:

00
01
10
11
根据 (4.1),

xy 不是同一数组的一部分。根据 (4.2),它们不是同一对象的成员。所以,你落入了(4.3),这意味着如果你试图将它们相互比较,比较的结果是 indeterminate,它 could 为真 为假。如果它是 未定义的行为,标准可能会明确说明。

C++ 标准的各个版本以及问题中引用的最新草案中的措辞都发生了变化。 (有关详细信息,请参阅我对该问题的评论。)

C++11 说:

Other pointer comparisons are unspecified.

C++17 说:

Otherwise, neither pointer compares greater than the other.

问题中引用的最新草案说:

Otherwise, neither pointer is required to compare greater than the other.

做出该更改是为了响应 issue 所说的“‘比较大’这个词是不必要的混淆”。

如果您查看标准草案中的上下文,很明显在其余情况下结果是未指定。引用自 [expr.rel](斜体字是我的总结):

The result of comparing unequal pointers to objects is defined in terms of a partial order consistent with the following rules:

  • [pointers to elements of the same array]

  • [pointers to members of the same object]

  • [remaining cases] Otherwise, neither pointer is required to compare greater than the other.

If two operands p and q compare equal, p<=q and p>=q both yield true and p<q and p>q both yield false. Otherwise, if a pointer p compares greater than a pointer q, p>=q, p>q, q<=p, and q<p all yield true and p<=q, p<q, q>=p, and q>p all yield false. Otherwise, the result of each of the operators is unspecified.

所以在这种情况下 < 运算符的结果是未指定的,但它没有未定义的行为。它可以是真也可以是假,但我认为不需要保持一致。程序的输出可以是 00011011.

中的任何一个