为什么要使用显然毫无意义的DO-而在C / C ++宏if-else语句? [英] Why use apparently meaningless do-while and if-else statements in C/C++ macros?

查看:130
本文介绍了为什么要使用显然毫无意义的DO-而在C / C ++宏if-else语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在许多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 a semicolon after your macro always means the same thing. Let's say you had 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语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆