-5
main()    
{

   int k = 5;

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

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

4

4 回答 4

6

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

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

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

于 2013-08-18T15:17:59.417 回答
4

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

两者&&||施加序列点。更具体地说,他们首先评估他们的左操作数。然后有一个序列点1。然后(当且仅当有必要确定结果时)他们评估他们的正确操作数。

可能还值得一提的是,由于 and 的相对优先级&&||表达式: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 | xis的结果x,它需要评估正确的操作数以获得正确的结果。因此,它++k再次计算,因此k递增到 7。然后将结果与 8 进行比较,并发现(显然)7 小于或等于 8——因此if 执行null 语句,它什么也不做)。

所以,在if语句之后,k已经增加了两次,所以它是7.


  1. 在 C++11 中,短语“sequence point”已被替换为诸如“sequenced before”之类的短语,例如:“如果计算第二个表达式,则与第一个表达式相关的每个值计算和副作用都会在每个值之前排序与第二个表达式相关的计算和副作用。” 最终,效果是一样的。
于 2013-08-18T15:22:03.280 回答
2

在以下:

当第一个条件为&&真时评估“某事”

||当第一个条件为 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

于 2013-08-18T15:38:13.007 回答
1

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

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

递增k到 6,然后其和&&操作数的 LHS 评估为假。

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

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

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

所以上面第2步的条件表达式就变成了:

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

增加到k7 然后它的:

0 || 7 <= 8     

因为你有;after if,所以无论 if 条件将评估 True 还是 Falseprintf()都会被调用k = 7

于 2013-08-18T15:19:14.083 回答