问题描述
在许多C / C ++宏我看到包裹在宏code什么似乎是一个毫无意义的做的,而
循环。下面举例说明。
的#define FOO(X)做{F(X);克(X); }而(0)
的#define FOO(X),如果(1){F(X);克(X); }其他
我看不到什么做的,而
在做什么。为什么不只是写这没有它?
的#define FOO(X)F(X);克(X)
的做...而
和 IF ... ELSE
在那里让这个一
宏后分号总是意味着同样的事情。比方说,你
有这样的事情你的第二个宏。
的#define BAR(X)F(X);克(X)
现在,如果你使用 BAR(X);
在 IF ... ELSE
语句,其中if语句的尸体被裹没有在大括号,你会得到一个坏的惊喜。
如果(corge)
BAR(corge);
其他
gralt();
以上code将扩展到
如果(corge)
F(corge);克(corge);
其他
gralt();
这是语法不正确,因为否则将不再与如果相关联。它没有帮助包裹在宏内花括号的东西,因为大括号后的分号是语法不正确。
如果(corge)
{F(corge);克(corge);};
其他
gralt();
有解决这个问题的方法有两种。第一种方法是使用逗号宏内序列语句,而不必在抢劫其表现得像一个前pression能力。
的#define BAR(X)F(X),G(X)
栏 BAR
以上版本扩展了上述code到下面,这是语法正确。
如果(corge)
F(corge),G(corge);
其他
gralt();
这不工作,如果不是的函数f(x)
你有code,需要自己的块走的更复杂的机构,为说例如声明局部变量。在最一般的情况下,解决方案是使用像做...而
来使宏为一个语句,需要一个分号不会产生混淆。
的#define BAR(X)做{\\
INT I = F(X); \\
如果(ⅰ→4)克(ⅰ); \\
}而(0)
您不必使用做...而
,你可以煮了的东西,如果别的...
还有,虽然当 IF ... ELSE
的内部膨胀 IF ... ELSE
它会导致一个,这可能使现有的其他叼着问题更加难以找到,如下面的code。
如果(corge)
如果(1){F(corge);克(corge); }其他;
其他
gralt();
问题的关键是在上下文的地方悬空分号是错误的使用了分号。当然,它可以(并且可能应该)在这一点上认为,这将是更好的申报 BAR
作为一个实际的功能,而不是一个宏。
在综上所述,做...而
有没有变通的C preprocessor的缺点。当与C风格指南告诉你裁员的C preprocessor,这是他们担心这种事情。
In many C/C++ macros I'm seeing the code of the macro wrapped in what seems like a meaningless do while
loop. Here are examples.
#define FOO(X) do { f(X); g(X); } while (0)
#define FOO(X) if (1) { f(X); g(X); } else
I can't see what the do while
is doing. Why not just write this without it?
#define FOO(X) f(X); g(X)
The do ... while
and if ... else
are there to make it so that asemicolon after your macro always means the same thing. Let's say youhad something like your second macro.
#define BAR(X) f(x); g(x)
Now if you were to use BAR(X);
in an if ... else
statement, where the bodies of the if statement were not wrapped in curly brackets, you'd get a bad surprise.
if (corge)
BAR(corge);
else
gralt();
The above code would expand into
if (corge)
f(corge); g(corge);
else
gralt();
which is syntactically incorrect, as the else is no longer associated with the if. It doesn't help to wrap things in curly braces within the macro, because a semicolon after the braces is syntactically incorrect.
if (corge)
{f(corge); g(corge);};
else
gralt();
There are two ways of fixing the problem. The first is to use a comma to sequence statements within the macro without robbing it of its ability to act like an expression.
#define BAR(X) f(X), g(X)
The above version of bar BAR
expands the above code into what follows, which is syntactically correct.
if (corge)
f(corge), g(corge);
else
gralt();
This doesn't work if instead of f(X)
you have a more complicated body of code that needs to go in its own block, say for example to declare local variables. In the most general case the solution is to use something like do ... while
to cause the macro to be a single statement that takes a semicolon without confusion.
#define BAR(X) do { \
int i = f(X); \
if (i > 4) g(i); \
} while (0)
You don't have to use do ... while
, you could cook up something with if ... else
as well, although when if ... else
expands inside of an if ... else
it leads to a "dangling else", which could make an existing dangling else problem even harder to find, as in the following code.
if (corge)
if (1) { f(corge); g(corge); } else;
else
gralt();
The point is to use up the semicolon in contexts where a dangling semicolon is erroneous. Of course, it could (and probably should) be argued at this point that it would be better to declare BAR
as an actual function, not a macro.
In summary, the do ... while
is there to work around the shortcomings of the C preprocessor. When those C style guides tell you to lay off the C preprocessor, this is the kind of thing they're worried about.
这篇关于为什么要使用显然毫无意义的DO-而在C / C ++宏if-else语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!