为什么在具有多个 AND OR 的 If 语句中添加括号会给出不同的结果?

Why adding bracket in If statements with Multiple AND OR gives different result?

我有一个简单的程序,其中包含 1 个 AND 和多个 OR 运算符,如下所示:

#include <iostream>

using namespace std;

int main()
{
    bool a = true;
    bool b = true;
    bool c = true;
    bool d = true;

    if (!a && b || c || d)
        cout << "run";
    else
        cout << "pass";

    return 0;
}

我希望程序会输出 pass,因为我将 a 声明为 true。但是,如果您 运行 程序,它将给出输出:run

如果我通过向

添加方括号来更改 if 语句行
if (!a && (b || c || d))
        cout << "run";
    else
        cout << "pass";

它将给出预期的输出pass。为什么会这样?

&& 运算符 优先级 高于 C++(以及大多数其他编程语言)中的 ||。所以,你的第一个版本的代码实际上就像你写的一样执行:

if ((!a && b) || c || d)  // if (false || true || true)
    cout << "run";
else
    cout << "pass";

当然,if 语句为真,因为 cd 在开始时都设置为 true

运算符优先级,如您在此处所见:https://en.cppreference.com/w/cpp/language/operator_precedence 意味着 && 将在 || 之前计算。

这是因为逻辑与运算符(&&)比逻辑或运算符(||)具有更高的precedence,而逻辑非运算符(!) 具有三者中最高的优先级。

这意味着表达式 !a && b || c || d 被分组为 ((((!a) && b) || c) || d)。从内到外工作:

  • !afalse -> (((false && b) || c) || d)
  • false && bfalse -> ((false || c) || d)
  • false || ctrue -> (true || d)
  • true || dtrue -> true

所以整个表达式的计算结果为 true

Tim 和 Miles 的答案正确,您应该接受其中一个。

我也想在这里解释一个编程概念,如果您打算为工作编写代码,那么这一点很重要。

了解运算符优先级非常重要,但您可能不想在代码出现问题时尝试用铅笔检查所有代码。因此,非常明确地编写代码会很有帮助。我会,而不是你写的,做这样的事情:

bool should_run(bool a, bool b, bool c, bool d) {
  if( ! a ) {
    return true;
  }
  return b || c || d;
}

if( should_run(a, b, c, d)) {
  cout << "run";
} else {
  cout << "pass";
} 

写的比较长?是的。阅读时间更长?可能是。更长时间地了解你在做什么?不,绝对不是。尤其是 2 个月后,当您尝试调试棘手的情况时,不记得为什么会有那么长的逻辑字符串。

评论更好:

// returns true if the conditions are right to run,
// otherwise, return false to indicate a pass.
bool should_run(bool a, bool b, bool c, bool d) {
  // if coach said we don't run, then we pass!
  if( ! a ) {
    return true;
  } // coach said pass.

  // if the tight end, halfback, or running back are ready, then run.
  // if all three are not ready, then I guess we're passing.
  return b || c || d;
}

if( should_run(a, b, c, d)) {
  cout << "run";
} else {
  cout << "pass";
} 

对于那些会抱怨执行效率的人:编译器可以通过内联来解决大部分的优化问题。如果没有,我说 "First make it work, later, when you discover a problem, make it work faster"。毕竟, “Premature optimization is the root of all evil (or at least of most of it) in programming”。

操作具有优先级,具有相同优先级值的操作将从左到右依次执行。