如何编译器编译 if 语句


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

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

++k < 5计算结果为 false (6 <5 = false(,因此不计算 && 运算符的 RHS(因为已知结果为 false(。 然后计算++k <= 8(7 <= 8 = true(,因此完整表达式的结果为true,并且k已递增两次,使其最终值为7。

请注意,&&|| 是短路布尔运算符 - 如果表达式的结果可以由左手参数确定,则不计算右手参数。

另请注意,与大多数运算符不同,短路运算符在表达式中定义序列点,这使得在上面的示例中在同一表达式中多次修改k是合法的(通常,如果不干预序列点,这是不允许的,并导致未定义的行为(。

与许多这样的问题不同,在我看来,您的代码实际上已经定义了行为。

&&||都强加序列点。更具体地说,他们首先评估他们的左操作数。然后是序列点1。然后(当且仅在必要时确定结果(他们评估其正确的操作数。

可能还值得一提的是,由于&&||的相对优先级,表达式:if(++k <5 && k++/5 || ++k<=8)等价于:if((++k <5 && k++/5) || ++k<=8)

因此,让我们一步一步来:

int k = 5;
if(++k <5 &&

所以,首先它评估这么多。这将递增k,因此其值变为 6。然后它进行比较以查看它是否小于 5,这显然会产生 false。

k++/5 

由于前一个结果是false的,所以这个操作数不会被计算(因为false && <anything>仍然总是产生false作为结果(。

|| ++k<=8); 

因此,当执行到达此处时,它已false || <something>.由于false | x的结果是x的,它需要计算正确的操作数才能得到正确的结果。因此,它会再次评估++k,因此k递增到 7。然后,它将结果与 8 进行比较,并发现(显然(7 小于或等于 8 - 因此,执行if后面的 null 语句(尽管作为 null 语句,它什么也不做(。

因此,在if语句之后,k增加了两次,因此7


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

在下面:

对于&&当第一个条件为 True 时评估"某物">

对于||当第一个条件为 False 时评估"某物">

( (++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

最初k在声明中被分配5,然后在以下 if 条件下分配:

   ++k < 5 && k++ / 5 || ++k <= 8
//  ^
// evaluates 

k递增到 6,则其和 LHS &&操作数的计算结果为 false。

6 < 5  && k++ / 5   ||  ++k <= 8     
// ^      ^^^^^^^
//   0    not evaluates 

然后由于&&运算符的短路行为k++ / 5将不会评估。

&

&运算符的短路行为为:
0 && any_expression == 0 ,所以any_expression不需要评估。

所以上面的步骤 2 条件表达式变成:

0 || ++k <= 8     
//   ^^^^^^^^   
//  evaluates 

k增加到 7,然后:

0 || 7 <= 8     

因为你在if之后有;,所以无论 if 条件是计算 True 还是 False,printf()都会用 k = 7 调用。

最新更新