main()
{
int k = 5;
if(++k <5 && k++/5 || ++k<=8); // how to compiler compile this statement
print f("%d",k);
}
//这里的答案是7,但是为什么?如何编译if语句
main()
{
int k = 5;
if(++k <5 && k++/5 || ++k<=8); // how to compiler compile this statement
print f("%d",k);
}
//这里的答案是7,但是为什么?如何编译if语句
在以下几点:当第一个条件是真
为||
“东西” 时,第一个条件是假
((++k <5) && (k++/5)) || (++k<=8)
(6 < 5 AND something) OR something
(False AND something) OR something
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
False OR 7 < 8
False OR True
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
True
所以k
为&&
“东西” 被评为评估出来是7
这可以使用更多的解释性文字。 –
POW不错!再次一个艺术的答案,可读! –
++k < 5
的计算结果为false(6 < 5 = false),因此&&
运算符的RHS未被评估(因为结果已知是错误的)。然后++k <= 8
进行评估(7 < = 8 =真),所以完整的表达式的结果为真,和k
已递增两次,使得其最终值7.
注意&&
和||
是short circuit布尔操作符 - 如果表达式的结果可以由左手参数确定,那么不评估右手参数。还请注意,与大多数操作员不同,短路操作员在表达式中定义了sequence points,这使得在上例中合法地在同一个表达式中多次修改k
(通常,在没有插入序列点的情况下这是不允许的结果在Undefined Behaviour)。
最初k
分配5
,在你的宣言,然后在if条件如下:
增量k
至6那么它和&&
操作的LHS判断为假。
6 < 5 && k++/5 || ++k <= 8
//^ ^^^^^^^
// 0 not evaluates
然后因为Short-Circuit behavior & &运营商的k++/5
不会评析。 & &运营商的
短路行为是:
0 && any_expression == 0
,所以any_expression
并不需要评估。
所以上面的步骤2的条件表达式变为:
0 || ++k <= 8
// ^^^^^^^^
// evaluates
增量k
到7,然后它的:
0 || 7 <= 8
,因为你有;
后if
,所以无论是否条件将判断为真或假printf()
将被调用k = 7
。
与许多像这样的问题不同,在我看来,你的代码实际上已经定义了行为。
&&
和||
均施加顺序点。更具体地说,他们首先评估它们的左操作数。然后有一个序列点。然后(当且仅当需要确定结果时),他们评估他们的右操作数。
它可能还值得一提的是由于&&
和||
,表达的相对优先级:if(++k <5 && k++/5 || ++k<=8)
相当于:if((++k <5 && k++/5) || ++k<=8)
。
那么,让我们拿东西,在一步一个脚印:
int k = 5;
if(++k <5 &&
因此,首先它的计算结果这么多。这增加了k
,所以它的值变为6.然后比较看看它是否小于5,这显然产生错误。
k++/5
由于先前的结果是false
,该操作数是不评价(因为false && <anything>
仍总是产生false
作为结果)。
|| ++k<=8);
所以,当执行到这里时,它有false || <something>
。由于false | x
的结果是x
,因此需要评估右操作数才能获得正确的结果。因此,它再次评估++k
,因此k
增加到7.然后它将结果与8进行比较,并且发现(显然)7小于或等于8 - 因此,在执行if
之后的空语句是执行(尽管是空语句,它什么都不做)。
因此,if
声明后,k
已经增加了两次,所以它的7
。 “如果第二表达式,每一个值计算和副作用相关联:
注意:短电路操作员是序列点。 –
**阅读**:[在C编程语言中&&的行为](http://stackoverflow.com/questions/18229657/behaviour-of-in-c-programming-language/18229763#18229763) –
如何声明是内部执行“if()” 如何:++ k <5 && k ++/5 || ++ k <= 8是否执行? –