int main() {
int a = 1;
int b = 0;
if (a = b || ++a == 2)
printf("T: a=%i, b=%i", a, b);
else
printf("F: a=%i, b=%i", a, b);
return 0;
}
让我们来看看这个简单的代码片段。结果是: T:a = 1,b = 0
为什么呢? (注意a=b
使用赋值操作数,而不是比较)
我在这里理解的是,零分配给 a ,然后 a 增加到1. 1不等于2所以结果确实应该是 a = 1,b = 0 。但为什么这个条件评估为真? (a=b)
或(++a == 2)
都不是......我错过了什么?
这是另一个按预期打印 F 的短程序:
int main() {
int a = 1;
int b = 0;
if (a = b) printf("T"); else printf("F");
return 0;
}
答案 0 :(得分:27)
你混淆了误导性的间距。
if (a = b || ++a == 2)
与:
相同if (a = (b || ((++a) == 2)))
这实际上有未定义的行为。虽然b
的评估与((++a) == 2)
的评估之间存在一个序列点,但隐含的a
分配与另一个a
的分配之间没有序列点。由于明确的=
分配。
答案 1 :(得分:2)
实际上,赋值具有最低的运算符优先级,因此if语句等效于:
if ( a = ( b || ( ++a == 2 ) ) )
所以你将a分配给1,但也在同一个表达式中递增它。我认为这会导致未定义的行为,但最终结果是编译器中的a为1。
答案 2 :(得分:0)
如果您正在使用具有类似有用警告的GCC或其他编译器,打开警告会给您一个非常大的提示,指出这里出了什么问题。使用gcc -Wall
:
警告:建议用作真值的分配括号
准确地说:编译器将代码解释为if (a = (b || ++a == 2))
,并且警告建议您将其编写为if ((a = (b || ++a == 2)))
以强调代码是预期的,而不是更多的错字共同if (a == (b || ++a == 2))
。
所以警告需要一些解释。为了获得所需的效果,巧合的是,您需要在用作真值的不同赋值周围添加括号,即(a = b)
。尽管如此,警告告诉您,对于这一特定代码行有些不妥,值得进一步审查。