【问题标题】:While conditions followed by ;While 条件后跟 ;
【发布时间】:2013-04-19 18:05:11
【问题描述】:

我被要求评论一些代码并描述它的作用。一切都很好,我很好地处理了 switch 案例中正在做的事情,但现在我不确定是否曾经遇到过任何案例。我目前不需要运行或测试此代码,因为我的主机和所有常规软件都已关闭。

除了默认情况外,是否会在此 while 循环的条件下使用开关的任何一种情况?我只是简单地增加到 32 并且 rByte 在它甚至进行切换之前就返回了吗?有什么用;之后的条件呢?后面不应该是 {....} 而不是 ; ?

while(pCommand[--Ptr.Five] > 10 && ++i <32);
if(i==32)
{
    return rByte;
}
switch(pCommand[Ptr.Five++])
{
    case 2: ... (lots of code)
           break;
    case 4: ...  (lots of cod)
           break;
    default: ...
           break;
}

另外,--Ptr.Five 与 Ptr.Five++ 相比如何处理?我的理解是第一个将指针移回并使用该值,而第二个使用当前值并发布增量。

我错过了什么吗?甚至移动过去;在 while 的条件和 while 之后缺少 {} 之后,Ptr.Five 的值不会 > 10,因此永远不会是 2 或 4?

使用 ;在这段时间的情况下,我会不会被撞到 32 并且如果会返回 rByte?

【问题讨论】:

  • 这段代码很糟糕。这是一次面试,找一个不同的雇主。

标签: c pointers while-loop


【解决方案1】:

循环

while(pCommand[--Ptr.Five] > 10 && ++i <32);

递减Ptr.Five并递增i直到

  • pCommand[Ptr.Five] &lt;= 10,或
  • i &gt;= 32,

以先发生者为准。由于对感兴趣变量的更改是在循环条件中完成的,因此循环体应该为空。 (不是说它的风格特别好,但我见过更糟糕的。)

如果i == 32,则未达到switch,否则,如果i &lt; 32,则您知道pCommand[Ptr.Five] &lt;= 10,因此可以达到两种非默认情况。

【讨论】:

    【解决方案2】:

    分号本身就是一个空语句。这样做例如

    while (complicated_expression)
        ;
    

    等同于:

    while (complicated_expression)
    {
    }
    

    经常在complicated_expression有副作用时使用,不需要循环体。

    【讨论】:

      【解决方案3】:
      while(pCommand[--Ptr.Five] > 10 && ++i <32);
      

      没有主体,但循环条件本身有副作用,所以它确实做了一些事情。

      我们可以重写为:

      while (1) {
          --Ptr.Five;
          if (pCommand[Ptr.Five] <= 10)
              break;
          ++i;
          if (i == 32)
              break;
      }
      if (i == 32) {
          /* we never hit the pCommand condition */
      }
      

      至于为什么

      • 它向后搜索pCommand,从偏移量Ptr.Five到之前最多32个条目,寻找一个值&lt;= 10
      • 如果在 32 个条目中没有找到这样的值,则返回 rByte
      • 如果它确实找到了这样的值,它会打开它并做一些工作
        • PtrFive 递增以指示该值之后的下一个条目,开关被调度

      另外,--Ptr.Five 与 Ptr.Five++ 相比如何处理?我的理解是第一个将指针向后移动并使用该值,而第二个使用当前值并发布增量。

      完全正确。在:

      pCommand[--Ptr.Five] > 10
      

      Ptr.Five 在计算表达式的其余部分之前递减,而在:

      pCommand[Ptr.Five++]
      

      Ptr.Five 值计算表达式,然后立即递增。在这里,这意味着切换基于 pCommand 中的旧条目(结束 while 循环的条目,因为它是 &lt;= 10),但 Ptr.Five 在 case 内的代码执行之前递增。


      关于副作用的快速说明:正如 John Bode 在评论中指出的那样,我对前减量和后增量表达式的描述并不十分准确。 这是因为将新值存储到Ptr.Five 不必 必须立即进行。 然而,由于它必须(好像)在下一个序列点(这里是&amp;&amp;)之前发生,所以没有真正的歧义。

      这通常只有在单个语句中将多个相互依赖的副作用表达式串在一起时才会成为问题。所以,你知道,尽量避免这种情况。

      【讨论】:

      • "Ptr.Five 在计算表达式的其余部分之前递减"——这并不完全正确。表达式--Ptr.Five结果Ptr.Five 的值减一,但在计算表达式的其余部分之前可能不会应用副作用
      • 非常感谢您的精彩解释!
      • 第一个if (i == 32)是错误的。 while 循环在 ++i &lt; 32 时迭代,因此中断条件是 i &gt;= 32,而不是 ==
      • 不,++i &lt; 32 pre-increments i,然后如果i的增量值不再小于32,则中断循环,即等于 32。
      【解决方案4】:

      假设 i 开始于 0 -- while 循环正在解析 pCommand 数组的 31 个元素 (1-31),在检查值之前递减 Ptr.Five,寻找小于的值比10。如果没有找到,该函数返回rByte——然后检查pCommand[Ptr.Five]的值递增之前......因此,在开关中使用的值与while 条件中使用的值。该值很可能是任何开关条件,因为我们知道它小于10

      【讨论】:

        【解决方案5】:

        无法回答您的问题。即使我们假设i0 开头,谁知道pCommand[Ptr.Five] 在此代码块开头的值是多少?

        解决一些可以回答的问题,如果我们像这样重写while会有所帮助:

        while(pCommand[--Ptr.Five] > 10 && ++i <32)
        {
            /* do nothing as the body of the loop... nothing at all. 
             * Everything happens in the condition.
             */
        }
        

        分号的语法是有效的,如果一开始有点混乱:想想分号在 C/C++ 中的含义(终止语句),然后想想在这种情况下终止的语句是什么(提示:它是“无操作”)。

        --Ptr.FivePtr.Five-- 的区别就是你描述的:第一个变体(预减量)会减量Ptr.Five,然后返回结果值;第二个变体(后递减)将递减Ptr.Five,但在递减之前返回值

        【讨论】:

          猜你喜欢
          • 2016-10-20
          • 2015-02-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-05
          • 2019-10-26
          相关资源
          最近更新 更多