【问题标题】:How to write safe and user friendly c/c++ #define macros如何编写安全且用户友好的 c/c++ #define 宏
【发布时间】:2014-05-03 12:25:46
【问题描述】:

我一直在思考如何将宏写成安全、可读和直观的。正确使用它们应该通过它们的外观来理解,当使用不正确时编译器应该告诉你,而不是让你引入一个晦涩的错误。

在编写多行定义宏时,我通常会发现自己像这样构造它们来满足所需的条件:

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

但是,我看到 SW 开发人员阅读了这种宏结构并对此感到非常困惑。你能想出替代方法来编写宏,这些宏不会以某种方式欺骗用户,让他们做一些超出预期的事情,并且在浏览一段新代码时仍然很容易理解?

另外,你能发现 do {} while(0) 方法有什么问题吗?例如,您可能希望宏以某种方式运行,但实际情况并非如此。

我不完全相信 do {} while(0) 方法是好的做法的原因是宏本身看起来有点奇怪,并且需要向以前没有看过该构造的任何人(至少有些人)进行一些解释.

编辑:

这是我喜欢的 cmets 中的链接之一的示例(谢谢!)。我认为它的可读性很强:

#define MYMACRO(a,b)   \
    if (xyzzy) asdf(); \
    else (void)0

可以破解吗?

【问题讨论】:

  • 是的,do {} while(0) 方法是最安全和推荐的!
  • do {} while(0) 是解决此问题的常用方法,特别是由于最后一行缺少分号使其看起来像一个函数。但是,我认为宏总是以某种方式“欺骗”用户,至少如果他们期望的是一个函数。
  • 如果你想让它安全,你为什么不写一个函数呢?
  • 我对宏使用全部大写的约定,以提醒用户参数可能会被多次评估,或者该行的效果可能不是用户期望的。
  • “如何编写用户友好的 c/c++ #define 宏”。简单:你不能:)

标签: c++ c c-preprocessor


【解决方案1】:

当您希望宏不执行任何操作并使用预处理器切换此行为时,一种常见的方法是使用void(0) 操作。

#if SOMETHINGS
#define macro(x)    do{                      \
                        ... some code line ; \
                        ... some code line ; \
                    }while(0)
#else
#define macro(x) ((void)(0))
#endif

这样你就不会在取消宏操作时中断编译

【讨论】:

  • 您可能不得不使用 else 版本,因为各种编译器会发出各种死代码警告。
  • 第二种情况下为什么不直接使用#define macro(x)
  • @FilipeGonçalves 因为如果你有像if (macro(x)) 这样的代码,你的代码不会在每次切换macro 的存在时编译
  • if (macro(x)) 无论如何都不会使用原始宏定义进行编译。 do while 构造不是表达式,因此不能在 if 中使用。我想说,如果将原始宏用作语句,那么#define macro(x) 就足够了。虽然我没有尝试过,但我猜if (((void)(0))) 也不会编译,因为您使用void 值作为测试条件。
  • 您可以看到here 对模拟no ops 的宏的解释。我以名称macro 为例,这个macro 不能出现在if 子句的正文中。另一个原因是在赋值发生的地方显式中断编译,以防止被排除宏的状态突变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 2014-05-20
相关资源
最近更新 更多