C++ 如何编写安全且用户友好的c/c++#定义宏
我一直在思考如何编写安全、可读和直观的宏。正确使用它们应该通过它们的外观来理解,如果使用不正确,编译器应该告诉您,而不是让您引入一个模糊的bug 在编写多行定义宏时,我通常会这样构造它们以满足所需的条件:C++ 如何编写安全且用户友好的c/c++#定义宏,c++,c,c-preprocessor,C++,C,C Preprocessor,我一直在思考如何编写安全、可读和直观的宏。正确使用它们应该通过它们的外观来理解,如果使用不正确,编译器应该告诉您,而不是让您引入一个模糊的bug 在编写多行定义宏时,我通常会这样构造它们以满足所需的条件: #define macro(x) do{ \ ... some code line ; \ ... some code line ; \
#define macro(x) do{ \
... some code line ; \
... some code line ; \
}while(0)
这样你们两个都可以
if (a)
{
macro(a);
}
而且
if (a)
macro(a);
else
{
...
}
它的一个很好的特性是,如果您不正确地使用它们,您将得到一个编译器错误。这不会编译,例如:
if (a)
macro(a)
else
b();
然而,我看到软件开发人员阅读了这种宏构造,并对此感到相当困惑。你能想出其他方法来编写宏吗?这些宏不会欺骗用户,让用户在浏览一段新代码时仍然可以理解
另外,您能发现do{}while(0)方法有什么问题吗?例如,在这种情况下,您可能希望宏以某种方式运行,但实际情况并非如此
之所以我不完全相信do{}while(0)方法是一种好的实践方法,是因为宏本身看起来有点奇怪,需要向以前没有见过该构造的任何人(至少有些人)解释一下
编辑:
下面是我喜欢的评论(谢谢!)中一个链接的例子。我认为它很可读:
#define MYMACRO(a,b) \
if (xyzzy) asdf(); \
else (void)0
有可能破坏它吗?当您希望宏不执行任何操作,并使用预处理器切换此行为时,一种常见的方法是使用
void(0)
操作
#if SOMETHINGS
#define macro(x) do{ \
... some code line ; \
... some code line ; \
}while(0)
#else
#define macro(x) ((void)(0))
#endif
这样,您就不会在清空宏操作时中断编译是的,
do{}while(0)
方法是最安全的,也是推荐的do{}while(0)
是实现这一点的常用方法,特别是因为最后一行没有分号,使它看起来像一个函数。但是,我认为宏总是以某种方式“欺骗”用户,至少如果他们希望得到一个函数。如果你希望它是安全的,为什么不写一个函数呢?我使用宏的所有大写约定,提醒用户,参数可以被多次评估,或者这句话的效果可能不是用户期望的。“如何编写用户友好的c/c++#定义宏”。很简单:你不能:)你可能不得不修改else
版本,因为不同的编译器会发出不同的死代码警告。为什么不在第二种情况下定义宏(x)?@FilipeGonçalves,因为如果你有类似if(macro(x))的代码
如果(macro(x))永远不会使用原始宏定义编译,则不会在每次切换宏的存在时编译代码do-while
构造不是表达式,因此不能在if
中使用。我想说,如果将原始宏用作语句,那么定义宏(x)
就足够了。虽然我没有尝试过,但我猜if((void)(0))
也不会编译,因为您使用void
值作为测试条件。您可以看到有关模拟无操作的宏的说明。我以名称macro
为例,这个macro
不能包含在if
子句的主体中。另一个原因是在发生赋值的地方显式中断编译,以防止排除的宏发生状态突变。