main()
{
int k = 5;
if(++k <5 && k++/5 || ++k<=8); // how to compiler compile this statement
print f("%d",k);
}
//这里的答案是7但是为什么?
答案 0 :(得分:6)
++k < 5
求值为false(6 <5 = false),因此不评估&&
运算符的RHS(因为已知结果为假)。然后评估++k <= 8
(7 <= 8 =真),因此完整表达式的结果为真,k
已递增两次,使其最终值为7。
请注意&&
和||
是short circuit布尔运算符 - 如果表达式的结果可以由左手参数确定,那么右手参数不会被评估。
另请注意,与大多数运算符不同,短路运算符在表达式中定义sequence points,这使得在上面的示例中在同一表达式中多次修改k
是合法的(通常这如果没有干预序列点,则不允许Undefined Behaviour)。
答案 1 :(得分:4)
与许多这样的问题不同,在我看来,您的代码实际上已经定义了行为。
&&
和||
都会强加序列点。更具体地说,他们首先评估他们的左操作数。然后是一个序列点 1 。然后(当且仅在必要时确定结果)他们评估他们的右操作数。
可能还值得一提的是,由于&&
和||
的相对优先级,表达式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 - 因此,null if
后面的语句是执行的(但是,它是一个空语句,它什么都不做)。
因此,在if
语句后,k
已经增加了两次,所以它是7
。
答案 2 :(得分:2)
以下内容:
对于&&
,在第一个条件为真时评估“某事”
表示||
“在第一个条件为假时评估某事”
( (++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
答案 3 :(得分:1)
最初k
在您的声明中被分配5
,然后在if条件中被分配:
++k < 5 && k++ / 5 || ++k <= 8
// ^
// evaluates
将k
增加到6然后它和&&
操作数的LHS评估为false。
6 < 5 && k++ / 5 || ++k <= 8
// ^ ^^^^^^^
// 0 not evaluates
然后因为&amp;&amp;的Short-Circuit behavior operator k++ / 5
将不会进行评估。
&amp;&amp; amp;的短路行为运营商是:
0 && any_expression == 0
,因此any_expression
无需评估。
因此,上面的第2步条件表达式变为:
0 || ++k <= 8
// ^^^^^^^^
// evaluates
将k
增加到7然后再增加:
0 || 7 <= 8
因为;
之后你有if
,所以无论条件是评估是真还是假,printf()
都会被k = 7
调用。