The do ... while
and if ... else
有没有办法做到这一点
宏后面的分号总是表示相同的意思。就说你吧
有类似你的第二个宏的东西。
#define BAR(X) f(x); g(x)
现在如果你要使用BAR(X);
in an 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
将上面的代码扩展为下面的代码,这在语法上是正确的。
if (corge)
f(corge), g(corge);
else
gralt();
这不起作用,如果不是f(X)
您有更复杂的代码体,需要放在自己的块中,例如声明局部变量。在最一般的情况下,解决方案是使用类似do ... while
使宏成为带有分号的单个语句,不会造成混淆。
#define BAR(X) do { \
int i = f(X); \
if (i > 4) g(i); \
} while (0)
你不必使用do ... while
,你可以用以下材料烹饪一些东西if ... else
同样,虽然当if ... else
在一个内部扩展if ... else
它导致“悬空的其他 http://en.wikipedia.org/wiki/Dangling_else”,这可能会使现有的悬空 else 问题更难找到,如以下代码所示。
if (corge)
if (1) { f(corge); g(corge); } else;
else
gralt();
重点是在悬空分号错误的情况下用完分号。当然,此时可以(并且可能应该)争论说最好声明BAR
作为实际函数,而不是宏。
综上所述,do ... while
是为了解决 C 预处理器的缺点。当那些 C 风格指南告诉您放弃 C 预处理器时,他们担心的是这种事情。