C++ 为什么结合赋值和相等检查的if语句返回true?

C++ 为什么结合赋值和相等检查的if语句返回true?,c++,if-statement,C++,If Statement,我一直在想一些初学者的错误,最后我犯了if语句中的错误。我对代码进行了一些扩展: int i = 0; if (i = 1 && i == 0) { std::cout << i; } inti=0; 如果(i=1&&i==0){ std::cout这与 不是 if ((i = 1) && (i == 0)) 因为&&和==的优先级都高于= if (i = (1 && (i == 0))) 它将1&&(i==0)的结果赋给

我一直在想一些初学者的错误,最后我犯了
if
语句中的错误。我对代码进行了一些扩展:

int i = 0;
if (i = 1 && i == 0) {
    std::cout << i;
}
inti=0;
如果(i=1&&i==0){
std::cout这与

不是

if ((i = 1) && (i == 0))
因为
&&
==
的优先级都高于
=

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

它将
1&&(i==0)
的结果赋给
i
。因此,如果
i
0
开始,则
i==0
true
,因此
1&&true
true
(或
1
),然后将
i
设置为
1
。然后,由于
1
为true,因此输入if块并打印分配给
i

的值,假设代码实际如下所示:

#include <iostream>
using namespace std;

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

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

因此
i
被设置为
1

它与解析从右向左的规则有关。 例如y=x+5。
所有子表达式都按重要性加权。 从右到左计算两个同等重要的表达式,&&expression侧首先执行,然后执行LHS

对我来说很有意义。

实际答案是:

  • 编译器给出“i==0”,其计算结果为true
  • 然后它将i=1计算为TRUE或FALSE,并且由于编译的赋值运算符从不失败(否则它们不会编译),因此它也将计算为TRUE
  • 由于这两条语句的计算结果均为true,并且true&&true的计算结果均为true,因此if语句的计算结果将为true
  • 作为证明,只需查看您输入的代码的编译器asm输出(所有注释都是我自己的):

    <> >上面的ASM输出来自CLAN,但我查看的所有其他编译器都给出了类似的输出。对于该站点上的所有编译器,无论它们是纯C还是C++编译器,都没有任何改变编译器的模式(默认为C++编译器的C++)

    的情况。
    请注意,编译器实际上并没有设置i=1,但i=TRUE(这意味着任何32位非零整数值)。这是因为&&运算符只计算语句是真是假,然后根据该结果设置结果。作为证明,尝试将i=1更改为i=2,您可以自己观察到不会有任何更改。请在

    Guys上使用任何联机编译器,这不是一个打字错误问题。OP想知道为什么会出现if语句是与此代码一起输入的,因为
    i
    设置为
    1
    。或者它是否分配
    1&&i==0
    的结果?初学者建议:他们不应使用此类“高级”语言构造。只需单独分配变量。这也将避免序列点可能出现的问题。实际代码中的这种代码通常看起来也很糟糕。这必然会在面试问题上结束。额外的代码真的有必要吗?很明显,情况会是这样,否则它不会运行。Not只是不必要的额外代码。答案无法清楚地解释运算符优先级。因为我们在挑剔的火车上……我看到一个
    使用名称空间std
    !有额外的代码-但它仍然不是错误的代码。答案仍然是对的。当然,它没有解释运算符优先级。但是有人可以建议添加它,我想n不要直接否决投票!哇,-4很苛刻,考虑到它正确地回答了问题,尽管可能不是最佳答案。它没有像其他答案那样扩展运算符优先级,但它在代码上下文中说明了这一点,因此认为
    =
    早于
    &
    的任何人都可以看到is苏。还有,是的,扩展是无关的,但我认为它没那么重要。我不相信如此微小的差异会导致人们投151票对-4票。@JörgWMittag这很酷。我喜欢它迫使你使用括号。基本上,
    I=!I;if(I)
    正确written@NathanOliver字体Fortress是一种非常酷的语言,它在很多方面都做对了。(首席设计师是Guy L.Steele,所以这并不奇怪。)不幸的是,它没有得到DARPA最后一轮的资助,随后被甲骨文封存。自然地,要求编译器发出少量警告会检测到这个错误,任何不假定int和boolean是等价的语言也会检测到这个错误。1)文档链接到C操作符优先级,而这个问题用C++来标记。两种不同的语言。2>)代码> i=1 < /Cord>是赋值[不是等价]操作符;2b)我可以向您保证,<代码>(i=0)< /> >将在C和C++中都被评估为false条件,因此它是否评估为真WRT“它从不失败”。有点误导。<代码>和CL,1;=运算符总是真的“当用C++来标记这个问题时,DOC链接到C操作符优先权。两种不同的语言”——当你把C和C++运算符优先级比较,这两个之间的区别是什么?它们在这个主题上有相同的优先级,这并不奇怪,因为C++是C的直接派生(或者另一种方式,C是C++语言的子集,所以它们当然有很多共同点,包括优先级)。。无论如何,我会修正我的帖子,以防混淆。“如果我错了,请纠正我,但我看不到这里有赋值”--然后让我纠正你!1是一个立即值,不是任何测试或计算的结果。它是所谓的“假定为真”值。发生的唯一测试是针对I==0语句,即--“cmp dword ptr”[rbp-8],0”。只有当它说“movzx edx,1”时,你才是正确的。根据我前面的所有帖子,应该有两个比较,但在现实生活中只有一个,每个主要编译器的asm输出都证明这些帖子是正确的
    if (i = 1 && i == 0) {
    
     if (i = (1 && i == 0)) {
    
    mov     dword ptr [rbp - 8], 0    ; i = 0;
    cmp     dword ptr [rbp - 8], 0    ; i == 0?
    sete    al                        ; TRUE (=1)
    mov     cl, al
    and     cl, 1                     ; = operator always TRUE
    movzx   edx, cl
    mov     dword ptr [rbp - 8], edx  ; set i=TRUE;
    test    al, 1                     ; al never changed,
                                      ; so final ans is TRUE