提问者:小点点

“不是必需的”==未定义的行为?


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

[Expr.Rel]#4:

比较指向对象的不相等指针的结果是根据与下列规则一致的偏序定义的:

(4.1)如果两个指针指向同一数组的不同元素,或指向它们的子对象,则需要指向下标较高的元素的指针比较大。

(4.2)如果两个指针递归地指向同一对象的不同非静态数据成员,或指向这些成员的子对象,则需要指向后声明的成员的指针进行更大的比较,前提是两个成员具有相同的访问控制([class.access]),两个成员都不是大小为零的子对象,且它们的类不是联合。

(4.3)否则,两个指针都不需要比另一个指针大。

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

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

是。。。

  • 有效的C++代码,输出为1100
  • 无效代码,因为它具有未定义的行为

换句话说,我知道(4.3)在这里确实适用,但我不确定其中的含义。 当标准说“它既可以是A也可以是B”时,这和说“它是未定义的”是一样的吗?


共3个答案

匿名用户

在C++标准的各个版本中,以及在问题中引用的最近的草案中,措辞都发生了变化。 (详见我对这个问题的评论)

C++11说:

未指定其他指针比较。

C++17说:

否则,两个指针的比较值都大于另一个指针。

问题中提到的最新草案说:

否则,两个指针都不需要进行大于另一个指针的比较。

这一修改是针对一个问题作出的,即“较大”一词不必要地使人混淆“。

如果您查看标准草案中的周围环境,很明显,在其余的情况下,结果是未指定的。 引用[expr.rel](斜体部分是我的摘要):

比较指向对象的不相等指针的结果是根据与下列规则一致的偏序定义的:

>

  • [指向同一数组元素的指针]

    “指向同一对象成员的指针”

    “剩余情况”否则,两个指针都不需要比另一个指针大。

    如果两个操作数pq比较相等,则p<=qp>=q都产生true,而pp>q都产生false。 否则,如果指针p的比较大于指针q,则p>=q,p>q,q>=p,qpq均产生trueppq>=pq>=p均产生false。 否则,每个运算符的结果都未指定。

    因此<运算符在这种情况下的结果是未指定的,但它没有未定义的行为。 它可以是真的也可以是假的,但我不认为它必须是一致的。 程序的输出可以是00011011中的任何一个。

  • 匿名用户

    对于提供的代码,适用以下情况:

    (4.3)否则,两个指针都不需要比另一个指针大。

    没有提到UB,因此严格地理解“两者都不需要”意味着每次评估比较的结果都可能是不同的。

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

    00
    01
    10
    11
    

    匿名用户

    xy不是同一个数组的一部分,根据(4.1)。 并且它们不是同一对象的成员,per(4.2)。 所以,你陷入了(4.3),这意味着如果你试图将它们彼此比较,比较的结果是不确定的,它可能是真的,也可能是假的。 如果它是未定义的行为,标准很可能会明确说明。