这是C ++中未定义的行为吗?

时间:2012-01-13 14:48:07

标签: c++ undefined-behavior

我想知道在这里的最后一个x中访问x是否是未定义的行为:

int f(int *x)
{
    *x = 1;
    return 1;
}

int x = 0;
if (f(&x) && x == 1) {
    // something
}

7 个答案:

答案 0 :(得分:13)

未定义的行为,因为operator &&是一个序列点

答案 1 :(得分:7)

定义明确。

参考 - C ++ 03标准:

第5节:表达式,第4段:

  除非另有说明,否则

&& amp;的特殊规则和|| ],单个运算符的操作数和单个表达式的子表达式的评估顺序以及副作用发生的顺序是未指定

in in,

  

第1.9.18节

     

评估以下表达式

a && b
a || b
a ? b : c
a , b
     

使用这些表达式中运算符的内置含义,在评估第一个表达式后有一个序列点(12)。

答案 2 :(得分:2)

已定义。 C / C ++进行延迟评估,并且定义首先计算并检查左表达式。如果是真的那么正确的就是。

答案 3 :(得分:2)

不,因为&&定义了必须在rhs之前计算lhs的顺序。

||?:,也有定义的订单。其他操作数没有。

在可比较的中:

int x = 0;
if (f(&x) & x == 1) {
    // something
}

然后它是未定义的。这里lhs和rhs都将按任意顺序计算。这种非短路的逻辑形式并不常见,因为短切通常被认为至少对性能有益,而且往往对正确性至关重要。

答案 4 :(得分:2)

这不是未定义的行为。原因取决于两个事实,两个足以给出定义的行为

  • 函数调用和终止是一个序列点
  • '&&' operator是一个序列点

以下也是定义的行为

int f(int *x) {
    *x = 1;
    return 1;
}

int x = 0;
if (f(&x) & (x == 1)) {
    // something
}

但是,您不知道x == 1是评估为true还是false,因为&的第一个或第二个操作数可以先评估。但是,这对于定义此代码的行为并不重要。

答案 5 :(得分:1)

它没有未定义,但它也不应该编译,因为你试图将一个指向x(&x)的指针分配给一个引用。

&&将从左到右进行评估(如果左侧评估为假,则评估将停止。)

编辑:随着更改它应该编译,但仍然会被定义(因为如果你使用指针或引用它并不重要)。

答案 6 :(得分:0)

它会将调用程序块中的局部变量x的地址作为参数传递给f(指向int的指针)。 f然后将参数(在堆栈上的临时变量)设置为地址1(这不会导致问题)并返回1.由于1为真,if()将继续评估x == 1,这是假的,因为主程序段中的x仍为0。

if块的主体不会被执行。

修改

使用新版本的问题,正文将被执行,因为在f()返回后,调用块中的x为1。