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