本文翻译自:do { … } while (0) — what is it good for? [duplicate]
Possible Duplicate: 可能重复: Why are there sometimes meaningless do/while and if/else statements in C/C++ macros? 为什么在C / C ++宏中有时会出现无意义的do / while和if / else语句?
I've been seeing that expression for over 10 years now. 我已经看了十多年了。 I've been trying to think what it's good for. 我一直在努力思考它有什么好处。 Since I see it mostly in #defines, I assume it's good for inner scope variable declaration and for using breaks (instead of gotos.) 因为我主要在#defines中看到它,所以我认为它对内部范围变量声明和使用中断(而不是gotos)有好处。
Is it good for anything else? 对其他事情有好处吗? Do you use it? 你用它吗?
参考:https://stackoom.com/question/14xu/做-而-有什么好处-重复
It is a way to simplify error checking and avoid deep nested if's. 这是一种简化错误检查并避免深层嵌套if的方法。 For example: 例如:
do { // do something if (error) { break; } // do something else if (error) { break; } // etc.. } while (0);Generically, do / while is good for any sort of loop construct where one must execute the loop at least once. 通常, do / while适用于任何类型的循环构造,其中必须至少执行一次循环。 It is possible to emulate this sort of looping through either a straight while or even a for loop, but often the result is a little less elegant. 它可以模仿这种通过的直循环的while甚至for循环,但结果往往是有点不太优雅。 I'll admit that specific applications of this pattern are fairly rare, but they do exist. 我承认这种模式的具体应用是相当罕见的,但确实存在。 One which springs to mind is a menu-based console application: 让人想到的是一个基于菜单的控制台应用程序:
do { char c = read_input(); process_input(c); } while (c != 'Q');It helps grouping multiple statements into a single one, so that a function-like macro can actually be used as a function. 它有助于将多个语句分组到一个语句中,因此类似函数的宏实际上可以用作函数。 Suppose you have 假设你有
#define FOO(n) foo(n);bar(n)and you do 你也是
void foobar(int n){ if (n) FOO(n); }then this expands to 然后这扩大到
void foobar(int n){ if (n) foo(n);bar(n); }Notice that the second call (bar(n)) is not part of the if statement anymore. 请注意,第二个调用(bar(n))不再是if语句的一部分。
Wrap both into do{}while(0), and you can also use the macro in an if statement. 将两者都包装到do {} while(0)中,也可以在if语句中使用宏。
It's the only construct in C that you can use to #define a multistatement operation, put a semicolon after, and still use within an if statement. 它是C中唯一可用于#define多语句操作,后面加分号,仍然在if语句中使用的结构。 An example might help: 一个例子可能有帮助:
#define FOO(x) foo(x); bar(x) if (condition) FOO(x); else // syntax error here ...;Even using braces doesn't help: 即使使用大括号也无济于事:
#define FOO(x) { foo(x); bar(x); }Using this in an if statement would require that you omit the semicolon, which is counterintuitive: 在if语句中使用它将要求您省略分号,这是违反直觉的:
if (condition) FOO(x) else ...If you define FOO like this: 如果你这样定义FOO:
#define FOO(x) do { foo(x); bar(x); } while (0)then the following is syntactically correct: 那么以下语法是正确的:
if (condition) FOO(x); else ....It is interesting to note the following situation where the do {} while (0) loop won't work for you: 有趣的是,要注意以下情况:在做{}而(0)循环不会为你工作:
If you want a function-like macro that returns a value, then you will need a statement expression : ({stmt; stmt;}) instead of do {} while(0): 如果你想要一个返回值的类函数宏,那么你将需要一个语句表达式 :({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; }