做{...}而(0) - 有什么好处?

时间:2008-11-02 21:36:18

标签: c loops

  

可能重复:
  Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?

我已经看到这种表达超过10年了。我一直在努力思考它有什么好处。因为我主要在#defines中看到它,所以我认为它适用于内部范围变量声明和使用中断(而不是gotos)。

对其他任何事情都有好处吗?你用它吗?

5 个答案:

答案 0 :(得分:444)

它是C中唯一可用于#define多语句操作,后面加分号,仍然在if语句中使用的构造。一个例子可能会有所帮助:

#define FOO(x) foo(x); bar(x)

if (condition)
    FOO(x);
else // syntax error here
    ...;

即使使用大括号也无济于事:

#define FOO(x) { foo(x); bar(x); }

if语句中使用它会要求您省略分号,这是违反直觉的:

if (condition)
    FOO(x)
else
    ...

如果你这样定义FOO:

#define FOO(x) do { foo(x); bar(x); } while (0)

然后以下语法正确:

if (condition)
    FOO(x);
else
    ....

答案 1 :(得分:98)

这是一种简化错误检查并避免深层嵌套if的方法。例如:

do {
  // do something
  if (error) {
    break;
  }
  // do something else
  if (error) {
    break;
  }
  // etc..
} while (0);

答案 2 :(得分:69)

它有助于将多个语句分组到一个语句中,因此类似函数的宏实际上可以用作函数。假设你有

#define FOO(n)   foo(n);bar(n)

你做了

void foobar(int n){
  if (n)
     FOO(n);
}

然后扩展到

void foobar(int n){
  if (n)
     foo(n);bar(n);
}

请注意,第二个调用(bar(n))不再是if语句的一部分。

在(0)中将两者都包装到do {}中,你也可以在if语句中使用宏。

答案 3 :(得分:17)

有趣的是注意以下情况:do {} while(0)循环不会为你工作:

如果你想要一个类似函数的宏来返回一个值,那么你需要一个statement expression :( {stmt; stmt;})而不是do {} while(0):


#include <stdio.h>

#define log_to_string1(str, fmt, arg...) \
    do { \
        sprintf(str, "%s: " fmt, "myprog", ##arg); \
    } while (0)

#define log_to_string2(str, fmt, arg...) \
    ({ \
        sprintf(str, "%s: " fmt, "myprog", ##arg); \
    })

int main() {
        char buf[1000];
        int n = 0;

        log_to_string1(buf, "%s\n", "No assignment, OK");

        n += log_to_string1(buf + n, "%s\n", "NOT OK: gcc: error: expected expression before 'do'");

        n += log_to_string2(buf + n, "%s\n", "This fixes it");
        n += log_to_string2(buf + n, "%s\n", "Assignment worked!");
        printf("%s", buf);
        return 0;
}

答案 4 :(得分:-4)

通常,do / while适用于任何类型的循环构造,其中必须至少执行一次循环。可以通过直接while或甚至for循环来模拟这种循环,但结果往往不那么优雅。我承认这种模式的具体应用是相当罕见的,但确实存在。让人想到的是一个基于菜单的控制台应用程序:

do {
    char c = read_input();

    process_input(c);
} while (c != 'Q');