我一直在思考一些初学者的错误,最后我在if语句上犯了一个错误。我将代码扩展为:
int i = 0;
if (i = 1 && i == 0) {
std::cout << i;
}
我已经看到if语句返回true,并且它将I计算为1。如果i在If语句中被赋值为1,为什么i == 0返回true?
我一直在思考一些初学者的错误,最后我在if语句上犯了一个错误。我将代码扩展为:
int i = 0;
if (i = 1 && i == 0) {
std::cout << i;
}
我已经看到if语句返回true,并且它将I计算为1。如果i在If语句中被赋值为1,为什么i == 0返回true?
当前回答
假设你的代码是这样的:
#include <iostream>
using namespace std;
int main() {
int i = 0;
if (i = 1 && i == 0) {
cout << i;
}
}
那么这个:
if (i = 1 && i == 0) {
评估作为
if (i = (1 && i == 0)) {
所以I被设为1。
其他回答
假设你的代码是这样的:
#include <iostream>
using namespace std;
int main() {
int i = 0;
if (i = 1 && i == 0) {
cout << i;
}
}
那么这个:
if (i = 1 && i == 0) {
评估作为
if (i = (1 && i == 0)) {
所以I被设为1。
实际的答案是:
编译器优先考虑"i == 0",其结果为true。 然后它将i=1计算为TRUE或FALSE,由于编译后的赋值操作符永远不会失败(否则它们不会编译),它也计算为TRUE。 由于这两个语句的值都为true,并且true && true的值为true,因此if语句的值将为true。
作为证明,只需查看编译器的asm输出你输入的代码(所有注释都是我自己的):
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
上面的asm输出来自CLANG,但我看过的所有其他编译器都给出了类似的输出。对于该站点上的所有编译器都是如此,无论它们是纯C还是c++编译器,都没有任何改变编译器模式的pragmas(对于c++编译器,默认为c++)。
请注意,你的编译器实际上并没有设置i=1,而是i=TRUE(这意味着任何32位非零整数值)。这是因为&&操作符只计算语句是TRUE还是FALSE,然后根据该结果设置结果。作为证明,尝试将i=1更改为i=2,您可以自己观察到没有任何变化。在编译器资源管理器中使用任何在线编译器自行查看
这与运算符优先级有关。
if (i = 1 && i == 0)
不是
if ((i = 1) && (i == 0))
因为&&和==的优先级都比=高。它真正的结果是
if (i = (1 && (i == 0)))
它将1 && (i == 0)的结果赋给i。因此,如果i从0开始,那么i == 0为真,因此1 && true为真(或1),然后i被设置为1。然后由于1为真,您进入if块并打印您分配给i的值。
它与解析从右到左的规则有关。 例如y = x+5。 所有子表达式都按重要性加权。 两个同等重要的表达式从右向左求值。首先完成&&表达式,然后是LHS。
对我来说很有道理。