"} while (0);"是否总是等同于"break;} while (1);"?

4

我已经比较了gcc汇编器的输出

do { 

// some code 

} while (0);

使用

do {
 
    // some code

    break; 
} while (1);

输出结果相同,无论是否进行优化,但是...

总是这样吗?

没有实验能够证明理论,它们只能表明它们是错误的。


15
为什么你要把不需要循环的代码放进 while 循环里? - jjnguy
3
在特定条件下,逻辑可能会调用“continue”命令,从而使循环重新开始。 - sunside
3
这句话的意思是:它是用来替代使用goto语句的:在退出条件下使用break。重构代码时,最好使用额外的函数,需要时返回。 - stefaanv
3
如果在循环中调用"continue",那么行为将会有所不同。 (@Markus, @jmucchiello) - jjnguy
4
do { } while (0) 是写宏的常见惯用语。如果使用不当,它会生成比其他替代方案更多的编译错误...至于带有breakwhile(1)...我不知道为什么会有用处。 - Stephen
显示剩余10条评论
6个回答

18

有一点不同:

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

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

如果没有continue存在,则它们应产生完全相同的代码。


1
也许它们不会生成相同的代码,但它们应该做大致相同的事情。 - zneak
可以将以下代码始终更改为类似于:do { /*code*/ } while(condition); /*code*/,至少是这个具体示例。 - ShinTakezou
@ShinTakezou 是的;唯一的实际原因可能是使用多个条件和/或交织的中断。 - Gianni

5
表单不等同。以下是一个无限循环的示例:
do {
    continue;
    break;
} while (1);

这不是:

do {
    continue;
} while (0);

4

编辑:在阅读了许多有关此问题的评论后,我承认我的答案是错误的。抱歉。

改为:

do{ 

//some code 

}while(0);

或者:

do{

//some code

 break; 
}while(1);

我建议使用以下代码:

我只会使用:

//some code

我不完全确定C++是否支持这样做,但如果您想限制变量的作用域,并且这就是您这样做的原因,只需使用花括号即可:
{

 // Some Code

}

不,我不想限制作用域,这是为了在块内使用break并到达结尾。 - Hernán Eche
7
使用一个 goto。不开玩笑。使用一个虚假的循环,以便你可以把 goto 伪装成其他单词,比直接使用 goto 更加邪恶。(我个人认为) - CB Bailey
1
@Hernan 如果是这样的话,我认为你应该使用if/else块来实现。或者,更好的方法是将代码放入一个方法中,并使用return提前退出代码。使用循环来完成if/else块的工作对我来说似乎有些错误。 - jjnguy
1
@Charles,循环结构被用于不同的原因,这与我最初回答时想的不同。现在我完全明白为什么有人想要这样做了。(但是,我仍然认为这不是一个好主意) - jjnguy
1
@jinguy:我见过的do { ... } while 0的主要用途是在宏中,因为它允许您编写包含多个语句的单个语句。块不完全等同于单个语句,因为{ ... };是两个语句,而do { ... } while 0;是一个语句(这很重要:考虑if (foo) bar(); else baz;)。这在C中大多适用,因为C++有更好的方法来编写函数类型的宏。 - David Thornley
显示剩余4条评论

4
马库斯的评论指向了这个答案:区别在于使用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:我不得不阅读这篇文章https://dev59.com/9XNA5IYBdhLWcg3wmfK5来理解你的代码=P,是的,那就是区别。 - Hernán Eche
@ Hernán Eche:很抱歉给您带来不便。我使用微软的VS2008进行所有工作 :) - Aoi Karasu

3

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


0

根据您的评论,您正在使用带有break的while循环,以便在满足某些条件时能够跳出“循环”。

如果这是您想要实现的:

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
-1:做出假设。使用do while可以在不需要if / else阶梯的情况下从函数调用链(例如设置)中提前退出。 - Gregor Brandt
@gbrandt:再看一遍。在“假设”指出给 OP 之前,完全不清楚 OP 想要什么。 - John Dibling
去掉重新回答的-1。 - Gregor Brandt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接