为什么编译器显示为真?
输出应该是假的,因为 false&&true 是假的。但是,编译器给出 1 作为输出。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 13;
bool flag = true;
cout << ((b - 4) < a) && !flag;
return 0;
}
回答
这是因为<<优先级高于&&,您的表达式应该是:
cout << (((b-4)<a) && !flag);
更详细的解释:
任何 C++ 编译器在处理源代码时所做的第一件事就是构造一个表示源代码的抽象语法树(AST)。AST 是一种树结构,它对不同的一元和二元运算符的优先级进行编码。您编写的表达式 ( cout << ((b - 4) < a) && !flag;)的 AST将如下所示:
&&
/
<< !
/
cout < flag
/
- a
/
b 4
我们怎么知道 eg&&必须是 AST 的根或者括号中的子表达式首先被评估?因为 C++运算符优先级规则是这样说的。这些类似于我们在纸上进行数学运算时使用的规则(例如在加法之前进行乘法),但扩展到该语言支持的所有运算符。
我们可以使用 AST 来查看该表达式的子表达式的计算顺序,一般规则是计算按“自下而上”的顺序进行,即从 AST 的叶子到根。在这种特殊情况下,评估可能(概念上)是这样发生的:
// left subtree
b - 4 = 9
9 < a = true
cout << true = cout (operator<< returns a reference to cout)
// right subtree
!flag = false
最后我们只剩下cout && false. cout实现operator bool允许它隐式转换为bool,true如果流没有错误,则产生。因为这里就是这种情况,我们最终得到true && false == false了未使用的值。
所以你可以看到你的程序输出,1因为在评估左子树期间,cout << true被执行了。之后,cout && !flag虽然格式良好,但基本上什么都不做,因为它没有副作用,而且您不会使用结果。