如何编译if语句编译

时间:2013-08-18 15:10:39

标签: c++ c compiler-construction

main()    
{

   int k = 5;

    if(++k <5 && k++/5 || ++k<=8);  // how to compiler compile this statement 
  print f("%d",k);
}

//这里的答案是7但是为什么?

4 个答案:

答案 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


  1. 在C ++ 11中,短语“序列点”已被替换为“之前排序”之类的短语,如下所示:“如果评估第二个表达式,则对与第一个表达式相关的每个值计算和副作用进行排序在每个值计算和与第二个表达式相关的副作用之前。“最终,效果是一样的。

答案 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调用。

相关问题