条件后的变量赋值&& (C)

时间:2017-10-13 09:24:38

标签: c conditional variable-assignment

我很好奇关于条件子句中变量赋值的C标准的确切定义。这是一个小例子:

int foo() {
  ...
}

int bar() {
  ...
}

int main () {
  int a, b, x, y;
  ...
  if ( (a = foo()) == x && (b = bar() == y ) {
    ...
  }
  ...
}

GCC测试显示,如果(a = foo()) != xb = bar()将不会被执行。一方面,这种行为是最佳的,因为它不会浪费任何时间计算bar()。但另一方面,b的值有些未定义,因为它取决于foo()的结果,实际上与b无关。

我想知道C标准中是否有明确的此类案例定义,以及该定义的原因是什么。最后,编写此类代码被认为是最佳实践

3 个答案:

答案 0 :(得分:0)

这非常简单:如果第一个参数的计算结果为0,则&&的第二个(即右手)参数将进行评估。

因此,如果(b = bar() == y )为0,则(a = foo()) == x进行评估。

事实上,这可能使b未初始化 - 可能是未定义的结果 - 是一个试金石,因为你不应该用这种方式编码。

可以使用

if ((a = foo() == x) & (b = bar() == y))

如果您希望始终评估双方:&不会被短路。但是如果参数可以计算为0或1以外的值(在这种情况下它们不是这样),请注意意外的效果。

答案 1 :(得分:0)

  

GCC测试显示,如果(a = foo())!= x,则b = bar()将不会被执行。

嗯,这是逻辑AND(&&)运算符的属性。

引用C11,章节§6.5.13,强调我的

  

与按位二进制&操作员,&&运营商保证从左到右的评估;   如果计算第二个操作数,则在评估之间存在一个序列点   第一和第二个操作数。 如果第一个操作数比较等于0,则第二个操作数   操作数未被评估。

也就是说,对于b赋值,你是对的,如果第一个操作数是FALSE,b的值仍然是不确定的,并且任何使用变量可能会导致undefined behavior

(其中之一)最佳实践,是在定义时初始化局部变量,以避免使用不确定的值。

答案 2 :(得分:0)

运算符&&短路评估组成:第二个子表达式仅在需要其结果时才进行评估,以确定整个表达式的结果。

在您的示例中,在表达式中:

(a = foo()) == x && (b = bar() == y)

如果第一个子表达式(a = foo()) == x被评估为false,则无论子表达式(b = bar() == y)将产生什么结果,上面表达式的结果也都是假的。

由于短路评估和(a = foo()) == x评估为false的事实,从不评估表达式(b = bar() == y)