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

Teh*_*tGR 213 c++ if-statement

我一直在思考一些初学者的错误,最后我得到了if陈述中的错误。我对此扩展了一些代码:

int i = 0;
if (i = 1 && i == 0) {
    std::cout << i;
}
Run Code Online (Sandbox Code Playgroud)

我已经看到if语句返回真实的,它couti作为1。如果在if语句中i分配1了if,为什么i == 0返回true

Nat*_*ica 387

这与运算符优先级有关

if (i = 1 && i == 0)
Run Code Online (Sandbox Code Playgroud)

不是

if ((i = 1) && (i == 0))
Run Code Online (Sandbox Code Playgroud)

因为&&==都比拥有更高的优先级=。真正起作用的是

if (i = (1 && (i == 0)))
Run Code Online (Sandbox Code Playgroud)

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

  • 自然地,如果要求编译器发出少量警告,就会检测到该错误, (5认同)
  • 任何不假定int和booleans等价的语言都可以使用。 (4认同)
  • @JörgWMittag太酷了。我喜欢它强迫您使用括号。 (2认同)

小智 16

假设您的代码实际上如下所示:

#include <iostream>
using namespace std;

int main()  {
    int i = 0;
    if (i = 1 && i == 0) {
        cout << i;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后这样:

if (i = 1 && i == 0) {
Run Code Online (Sandbox Code Playgroud)

评估为

 if (i = (1 && i == 0)) {
Run Code Online (Sandbox Code Playgroud)

i设置为1

  • 额外的代码真的必要吗?看起来确实很明显,因为否则就无法运行。 (39认同)
  • 既然我们在nitpick火车上...我看到一个`using namespace std`! (34认同)
  • 哇,-4很苛刻,考虑到这可以正确回答问题,尽管可能不是最佳选择。它并没有像其他答案那样扩展运算符的优先级,但是它确实在代码的上下文中说了足够多的内容,因此任何认为`=`出现在`&amp;&amp;`之前的人都可以看到问题。另外,是的,扩展是无关紧要的,但我认为它没有那么重要。我不敢相信如此微小的差异会导致人们以151比-4的比例通过投票。 (14认同)
  • 不仅不必要的额外代码。答案无法清楚地说明运算符的优先级。 (13认同)
  • 有额外的代码-但它仍然不是错误的代码。答案仍然是正确的。当然,它不能解释运算符的优先级。但是有人建议添加它,而不是直接投票! (8认同)
  • 另外,我看到如果扩展基于问题的前几个修订版本之一,那么扩展就不会那么多余。“使用命名空间std”上的青年人挑剔,但Neil只是添加了它,因为TehMattGR的问题的第一个修订版要求它有意义。这是我希望我可以拒绝评论的情况之一。 (6认同)
  • @JoL我觉得这里看到的投票差异是一个典型的例子,说明了很多stackoverflow变成了什么...我知道40多个离线/在线的人都因为...原因而从未参与。 (6认同)
  • @JoL它不需要`使用命名空间std`来理解。使用std :: cout可以很好地完成这项工作,而没有前者的臭名昭著的问题。 (2认同)
  • @DavidConrad在问题的上下文中没有关系,对吗?这个问题在第一个修订版中仅使用了`cout`,而Neil扩展到了OP中文件中最可能的猜测,只是用来表明他假设`cout`来自`std`而不是其他东西。尼尔(Neil)在这里没有提倡使用“使用命名空间std”。如果这就是为什么现在几乎同时在同一时间发布的几乎相同答案的投票数是251票对4票的原因,以及为什么我在这里来到尼尔时只有-4票,我觉得这完全荒谬。 (2认同)
  • @JoL将其放在StackOverflow答案中肯定会促进它。 (2认同)
  • @JoL我在评论中批评了它的用法并指出了如何避免它。人们将SO答案视为模仿的模型。当一个新手出现并看到某人的声誉达到28k时,他们可能会认为该代码是好的代码,除非有警告。这个答案还算不错,但是在对不良行为进行建模时却不加任何提及,却没有为接受的答案添加任何内容。如果“多么糟糕”,答案应该这么多。 (2认同)