do{} while(0)的意义

3
当while循环内的条件始终为0(即始终为false)时,do while循环的意义是什么?
do
{

//some code implementation.

}while(0);

我在很多地方看到了这种用法。它的重要性是什么,我们不能只省略do while(0)吗?因为两种方式都只执行一次代码。

这不是重复的问题,因为我特别询问了while(0)条件的使用,而不是一般的do-while循环。


3
如果这不是一个宏,那么很可能是为了让作者能够使用break;跳转到块的末尾。有些人想要避免无论代价如何都要使用goto - Daniel Fischer
2
@levengli:不,这不是重复的。Daniel:有些语言(如Java)没有“goto”关键字,因此需要使用标记的break或do/while来跳转到特定点。后者更可取,因为标记的break语法可能会令人困惑。 - Thorsten S.
1
同意Thorsten的观点,这不是重复的。因此,使用它的主要原因是在不使用goto等语句的情况下执行跳转。 - Aragon
do { /* block */ } while (0); 执行一段代码块一次,以分号结束(与 { /* block */ } 相比)。这对于某些宏是必需的。 - pmg
把它看作是C语言版本的 try { ... } catch(),其中 break 的作用类似于 throw() - SF.
显示剩余3条评论
3个回答

2

它可以用于在任何地方离开代码的某个范围而不离开函数。考虑以下代码:

do
{
  beginAtomicOperationSequence();

  ret = doSomething();
  if (ret < 0) break;

  ret = doSomething2();
  if (ret < 0) break;

} while(0);

if (ret < 0) {
  switch (ret) {
   //handle error
  }
  rollbackAboveOperations();
} else {
  commitAboveOperations();
}

有些情况下,我认为这是可以接受的,特别是当需要执行一系列被视为原子操作的操作时。就像上面的例子。


1
参考“*...不好的实践...*”:级联的 if(...) if (...) if (...) ... 值得商榷,而 goto 更加糟糕! - alk
@alk 值得吗?更糟糕吗?无论如何,正如我所说的,只有在某些情况下才是可以接受的。诚然,级联的ifs从代码可读性方面来看要糟糕得多。 - Dariusz
@ThorstenS。以一种不需要这样的结构设计代码。更加深思熟虑地将代码分割为函数。单独处理每个返回代码。但是,我会更改我的答案中的良好实践部分,因为它具有误导性,而且并不是我想表达的意思。 - Dariusz
1
@Dariusz:对于像C这样的许多语言来说,这不是一个选项,因为必须处理返回代码,即使您有能力,我也不确定您是否应该尝试避免它。这个结构的典型处理方式是执行需要许多独立步骤的操作,任何失败的步骤都会导致失败。do/while解决方案很好,因为它易于理解和无聊,是KISS的完美候选人。 - Thorsten S.
1
"break"只是没有标签的“goto”,但由于拼写不同,它允许人们对一个过时的文章添加一个引人注目的标题,并谈论一个与现代软件工程无关的神秘主题。 - Art
显示剩余13条评论

2
它确保无论调用代码中使用了什么样的分号和花括号,宏始终表现一致。

有关更多详细信息,请参阅this


1

do { } while(0) 在这种情况下,是一种不透明的编写goto的方式,而不实际编写它。它被货柜崇拜程序员使用,他们在某个地方读到了goto很糟糕,但不理解为什么。

这里是Dariusz答案的示例,使用适当的goto和有意义的标签进行重写。

  beginAtomicOperationSequence();

  ret = doSomething();
  if (ret < 0) goto handle_error;

  ret = doSomething2();
  if (ret < 0) goto handle_error;

  ...

handle_error:
  if (ret < 0) {
    switch (ret) {
    //handle error
    }
    rollbackAboveOperations();
  } else {
    commitAboveOperations();
  }

可以看出来,它更短并且完全明显。你甚至不得不询问那个结构的目的,说明它是一个坏主意

我对我的答案非常强烈,因为我有一个同事在我们的项目中滥用它,我没有找到任何可赎回的价值。当你在其中添加一些真正的循环时,它变得更加恼人。然后就开始寻找breakcontinue将带你去哪里的乐趣了。


我认为这段代码不好。并不是因为goto语句的问题。handle_error应该处理错误,而不是在一切正常时执行提交操作。正确的做法是在所有都正常的返回语句之后放置handle_error - Dariusz
顺便说一句:这个回答与问题无关。你应该删除它。 - Dariusz
我重新表述了一下,以便提供一个恰当的答案,而且我不会删除它。在我看来,这个结构永远不应该被使用,没有任何好处。 - Patrick Schlüter
更有可能的是,do while(0) 用于在从 if(x) FUNCTION_LIKE_MACRO(); 调用时防止函数式宏失控。 - Lundin
个人而言,我不写goto语句,也不写类似函数的宏,并且我总是使用“{}”。因此,我从不编写do-while(0)。但是,我从来不喜欢将晦涩难懂的程序结构作为元编程问题的解决方案,这些问题是由程序员自己创建的。很奇怪,不是吗? - Lundin
显示剩余2条评论

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