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

问题描述

在许多C / C ++宏中,我看到的宏代码包裹在看起来毫无意义的 do while 循环中。以下是示例。

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)


推荐答案

做...而和 if ... else 可以使之成为宏,因此宏后面的
分号始终表示一样。假设您
有第二个宏。

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)

现在如果要使用 BAR(X); 在 if ... else 语句中,如果if语句的主体没有用大括号括起来,您会感到很惊讶

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();

以上代码将扩展为

if (corge)
  f(corge); g(corge);
else
  gralt();

这在语法上是不正确的,因为else不再与if关联。在宏中用大括号将内容包装起来无济于事,因为大括号后的分号在语法上是错误的。

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)

bar的上述版本 BAR 将上面的代码扩展为以下代码,从语法上讲是正确的。

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();

如果不是 f(X)您需要编写一个更复杂的代码体,例如,声明局部变量。在最一般的情况下,解决方案是使用 do ... while 之类的方法来使宏成为一个使用分号而不引起混淆的单个语句。

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)

您不必使用 do ...而的话,也可以用来煮东西,否则... $ ,尽管 if ... else 在 if ... else 内扩展,它会导致 ,这会使现有的晃来晃去的问题更加难以发现,如下面的代码所示。

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();

重点是在悬挂的分号错误的情况下用完分号。当然,在这一点上可能(也许应该)认为,最好将 BAR 声明为实际函数,而不是宏。

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.

总而言之, do ...而可以解决C预处理程序的缺点。当这些C风格指南告诉您解雇C预处理程序时,这就是他们担心的事情。

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-while和if-else语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 17:01