为什么这个if语句结合赋值和相等性检查返回true?

时间:2019-05-22 20:38:41

标签: c++ if-statement

我一直在思考一些初学者的错误,最后我在if语句中犯了一个错误。我对此扩展了一些代码:

int i = 0;
if (i = 1 && i == 0) {
    std::cout << i;
}

我已经看到if语句返回true,并且cout的{​​{1}}为i。如果在if语句中为1分配了i,为什么1返回i == 0

4 个答案:

答案 0 :(得分:341)

这与operator precedence有关。

if (i = 1 && i == 0)

不是

if ((i = 1) && (i == 0))

因为&&==的优先级都高于=。真正起作用的是

if (i = (1 && (i == 0)))

1 && (i == 0)的结果分配给i。因此,如果i0开始,那么i == 0true,因此1 && truetrue(或1),并且然后i被设置为1。然后,由于1为true,因此输入if块并打印您分配给i的值。

答案 1 :(得分:9)

假设您的代码实际上是这样的:

#include <iostream>
using namespace std;

int main()  {
    int i = 0;
    if (i = 1 && i == 0) {
        cout << i;
    }
}

然后这个:

if (i = 1 && i == 0) {

评估为

 if (i = (1 && i == 0)) {

,因此i被设置为1

答案 2 :(得分:-3)

实际答案是:

  1. 编译器将precedence赋予“ i == 0”,其结果为true。
  2. 然后,它将i = 1评估为TRUE或FALSE,并且由于编译后的赋值运算符永远不会失败(否则它们将不会编译),因此它的评估结果也为true。
  3. 由于两个语句的计算结果均为true,并且TRUE && TRUE的计算结果为TRUE,因此if语句的计算结果为TRUE。

作为证明,只需查看您输入的代码的编译器的asm输出(所有注释都是我自己的):

void PrimeFind (std::vector<bool> &vec)
{
  int vsize = vec.size();
  size_t sqvsize = ceil(sqrt(vsize));

  std::fill(vec.begin(), vec.end(), true);
  vec[0] = false;
  vec[1] = false;

  for (int i = 4; i < vsize; i += 2)
  {
    vec[i] = false;
  }

  for (int i = 3; i < sqrtvsize; i += 2)
  {
    if (vec[i])
    {
      for (int j = i * i; j < vsize; j += i)
      {
        vec[j] = false;
      }
    }
  }
}

上面的asm输出来自CLANG,但是我看过的所有其他编译器也提供了类似的输出。

请注意,您的编译器实际上并未设置i = 1,但是i = TRUE。这是因为&&运算符仅评估语句是TRUE还是FALSE,然后根据该结果设置结果。作为证明,尝试将i = 1更改为i = 2,您可以自己观察到什么都不会改变。在Compiler Explorer

上使用任何在线编译器亲自查看

答案 3 :(得分:-5)

它与解析从右到左的规则有关。 例如y = x + 5。
所有子表达式的重要性都得到加权。 从右到左评估两个具有同等重要性的表达式。首先完成&&表示端,然后是LHS。

对我很有道理。