【问题标题】:Is "} while (0);" always equal to "break;} while (1);"?是 "} 而 (0);"总是等于“break;} while (1);”?
【发布时间】:2010-06-11 14:48:55
【问题描述】:

我比较了 gcc 汇编器的输出

do { 

// some code 

} while (0);

do {
 
    // some code

    break; 
} while (1);

输出是相等的,有或没有优化但是..

总是这样?

没有实验可以证明理论,它们只能证明它们是错误的

【问题讨论】:

  • 你为什么要把代码放到一个不循环的while循环中?
  • 逻辑可能是在某些情况下会调用“继续”,再次循环。
  • 它是使用 goto 的替代品:break on exit-conditions。重构时,使用额外的函数并在需要时返回是值得的。
  • 那么,如果在循环中调用 continue ,行为会有所不同。 (@Markus,@jmucchiello)
  • do { } while (0) 是编写宏的常用习语。如果使用不当,它会产生比替代方案更多的编译错误......至于while (1)break......我不知道为什么会有用。

标签: c++ c while-loop break do-while


【解决方案1】:

略有不同:

do {
  // code
  if ( condition )
    continue;
  // code
  break;
} while(1);

condition 为真时将重新启动循环,而在} while(0); 版本中,continue 将等效于break

如果不存在continue,那么它们应该生成完全相同的代码。

【讨论】:

  • 也许他们不会产生相同的代码,但他们应该做同样的事情。
  • 可以随时更改为:至少do { /*code*/ } while(condition); /*code*/,具体示例
  • @ShinTakezou 是的;唯一实际的原因可能是使用多个条件和/或交错中断。
【解决方案2】:

形式不等价。这是一个无限循环:

do {
    continue;
    break;
} while (1);

这不是:

do {
    continue;
} while (0);

【讨论】:

    【解决方案3】:

    编辑:在阅读了有关此事的各种 cmets 后,我承认这个答案是错误的。对不起。

    代替:

    do{ 
    
    //some code 
    
    }while(0);
    

    或:

    do{
    
    //some code
    
     break; 
    }while(1);
    

    我只会使用:

    //some code
    

    我不能 100% 确定你是否可以在 c++ 中做到这一点,但如果你想限制变量的范围,这就是你这样做的原因,只需自己使用花括号:

    {
    
     // Some Code
    
    }
    

    【讨论】:

    • 如果你想中断或继续怎么办?
    • @jmucchiello:使用goto。不认真。使用假循环以便您可以将goto 伪装成其他词比首先使用goto 更邪恶。 (恕我直言)
    • @Hernan 如果是这样,那么我认为您应该使用 if/else 块来实现这一点。或者,甚至更好的是,将代码放入一个方法中,并使用 return 尽早中断代码。使用循环来完成 if/else 块的工作对我来说似乎很糟糕。
    • @Charles,使用循环结构的原因与我第一次回答时的想法不同。现在完全可以理解为什么有人想要这样做了。 (但是,我仍然认为这不是一个好主意)
    • @jinguy:我看到do { ... } while 0 的主要用途是在宏中,因为它允许您编写包含多个语句的单个语句。块并不完全等同于单个语句,因为{ ... }; 是两个语句,而do { ... } while 0; 是一个(这很重要:考虑if (foo) bar(); else baz;)。这主要适用于 C,因为 C++ 有更好的方法来编写函数类型的宏。
    【解决方案4】:

    Markus 的评论为我指出了这个答案:不同之处在于使用 continue 关键字时。

    在这种情况下:

    int _tmain(int argc, _TCHAR* argv[])
    {
        int i = 0;
        do {
            ++i;
            _tprintf(_T("Iteration %d\n"), i);
            if (i < 30) continue;
        } while(0);
    
        return 0;
    }
    

    你得到只有一次迭代,而在这种情况下:

    int _tmain(int argc, _TCHAR* argv[])
    {
        int i = 0;
        do {
            ++i;
            _tprintf(_T("Iteration %d\n"), i);
            if (i < 30) continue;
            break;
        } while(1);
    
        return 0;
    }
    

    您将获得 30 次迭代。在VS2008下测试。

    【讨论】:

    • Karasu:我必须阅读这个 stackoverflow.com/questions/895827/… 才能理解你的代码 =P,是的,这就是区别
    • @Hernán Eche:很抱歉给您带来不便。我所有的工作都使用微软的 VS2008 :)
    【解决方案5】:

    do while 子句在逻辑上是等价的。它们是否被翻译成相同的字节码取决于手头的编译器。我想大多数现代编译器都会平等对待它们。

    【讨论】:

      【解决方案6】:

      根据您对breaks 使用一段时间的评论进行编辑,以便能够在满足某些条件时跳出“循环”。

      如果这是你想要完成的:

      do
      { 
        // processing step 1
        if( some_condition )
          break;
        // processing step 2
        if( some_condition )
          break;
        // etcetera..
      } while(0)
      

      ...然后将您在 while 循环中的代码分解为具有多个返回的独立函数:

      void processing()
      {
      
        // processing step 1
        if( some_condition )
          return;
        // processing step 2
        if( some_condition )
          return;
        // etcetera..
      }
      
      int main()
      {
        // ...
        processing();
        return 0;
      }
      

      【讨论】:

      • -1:做出假设。 do while 可用于在没有 if/else 阶梯的情况下提前退出一系列函数调用(例如设置)。
      • @gbrandt:再看一遍。在向 OP 指出“假设”之前,完全不清楚 OP 想要什么。
      • 在重新措辞时删除了 -1。
      猜你喜欢
      • 2010-11-07
      • 2019-12-23
      • 1970-01-01
      • 2015-12-13
      • 2014-01-14
      • 2013-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多