其他分享
首页 > 其他分享> > c – 为什么在宏中使用明显无意义的do-while和if-else语句?

c – 为什么在宏中使用明显无意义的do-while和if-else语句?

作者:互联网

在许多C/C++宏中,我看到宏的代码包含在看似无意义的while循环中.这是一些例子.

#define FOO(X) do { f(X); g(X); } while (0)
#define FOO(X) if (1) { f(X); g(X); } else

我无法看到他们在做什么.为什么不在没有它的情况下写这个?

#define FOO(X) f(X); g(X)

解决方法:

do … while和if … else是为了让它成为一个
你的宏之后的分号总是意味着同样的事情.我们说你
有像你的第二个宏.

#define BAR(X) f(x); g(x)

现在如果你要使用BAR(X);在if … else语句中,if语句的主体没有用大括号括起来,你会得到一个不好的惊喜.

if (corge)
  BAR(corge);
else
  gralt();

上面的代码将扩展为

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

这在语法上是不正确的,因为else不再与if相关联.在宏中用大括号括起来是没有用的,因为大括号后面的分号在语法上是不正确的.

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

有两种方法可以解决问题.第一种方法是使用逗号对宏中的语句进行排序,而不会使其具有像表达式一样的能力.

#define BAR(X) f(X), g(X)

上面的bar BAR版本将上面的代码扩展为以下代码,这在语法上是正确的.

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

如果代替f(X),你有一个更复杂的代码体,需要进入它自己的块,比如声明局部变量,这是行不通的.在最一般的情况下,解决方案是使用类似do …的同时使宏成为单个语句,其中分号不会混淆.

#define BAR(X) do { \
  int i = f(X); \
  if (i > 4) g(i); \
} while (0)

你不必使用do … while,你也可以使用if … else做一些东西,尽管当if … else扩展到if … else时它会导致“dangling else” ,这可能使现有悬挂的其他问题更难找到,如下面的代码所示.

if (corge)
  if (1) { f(corge); g(corge); } else;
else
  gralt();

关键是在悬挂分号错误的情况下用掉分号.当然,它可能(也可能应该)在这一点上争论说,将BAR声明为实际函数而不是宏是更好的.

总之,do … while可以解决C预处理器的缺点.当那些C风格指南告诉你裁掉C预处理器时,这是他们担心的事情.

标签:c-3,c,c-preprocessor,c-faq
来源: https://codeday.me/bug/20190910/1802347.html