【问题标题】:how to compiler compile if statement [duplicate]如何编译编译if语句[重复]
【发布时间】:2013-08-20 11:08:06
【问题描述】:
main()    
{

   int k = 5;

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

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

【问题讨论】:

  • 注意:短路算子是序列点。
  • @ankitdixit:您需要了解 C 和 C++ 中 &amp;&amp;|| 的短路行为,因此请随时搜索和阅读。
  • 您缺少 main 的返回类型 (int)。 ifprintf 无关;它只控制空语句;
  • 当你问为什么输出是这样的时候,解释你的期望也是很好的。而main()在C++中是非法的,需要拼出返回类型int

标签: c++ c compiler-construction


【解决方案1】:

++k &lt; 5 的计算结果为 false (6 && 运算符的 RHS(因为已知结果为 false)。然后对++k &lt;= 8 求值(7 k 增加了两次,使其最终值为 7。

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

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

【讨论】:

    【解决方案2】:

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

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

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

    所以,让我们一步一步来:

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

    所以,首先它评估了这么多。这增加了k,所以它的值变成了6。然后它比较看看它是否小于5,这显然会产生错误。

    k++/5 
    

    由于之前的结果是false,因此评估此操作数(因为false &amp;&amp; &lt;anything&gt; 仍然总是产生false 作为结果)。

    || ++k<=8); 
    

    所以,当执行到这里时,它有false || &lt;something&gt;。由于false | x 的结果是x,所以需要对正确的操作数求值才能得到正确的结果。因此,它再次评估++k,因此k 递增到7。然后将结果与8 进行比较,并发现(显然)7 小于或等于8——因此,@ 后面的空语句987654339@ 执行(虽然,作为一个空语句,它什么也不做)。

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


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

    【讨论】:

      【解决方案3】:

      如下:

      对于&amp;&amp;,当第一个条件为真时评估“某事”

      对于|| "something" 在第一个条件为 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

      【讨论】:

      • 这可以使用更多的解释性文字。
      • 战俘不错!又是一个艺术的答案,可读!
      【解决方案4】:

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

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

      k 增加到 6,然后其和 &amp;&amp; 操作数的 LHS 评估为 false。

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

      然后因为 && 运算符 k++ / 5Short-Circuit behavior 将不会计算。

      && 运算符的短路行为是:
      0 &amp;&amp; any_expression == 0,所以any_expression 不需要计算。

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

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

      k 增加到 7,然后是:

      0 || 7 <= 8     
      

      因为在if 之后有;,所以无论条件是判断为真还是假,printf() 都将使用k = 7 调用。

      【讨论】:

        猜你喜欢
        • 2014-07-19
        • 1970-01-01
        • 1970-01-01
        • 2018-06-24
        • 2015-10-24
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多