11

对于调试日志,我经常看到并使用类似的东西

#ifdef DEBUG
    #define DLOG(fmt, args...) printf("%s:%d "fmt,__FILE__,__LINE__,args)
#else
    #define DLOG(fmt, args...)
#endif

但在很多地方,我看到第二个#define被替换为

#define DLOG(fmt, args...) do {} while (0)

特别是,有这个答案,并且对同一问题的另一个答案的评论表明问题将出现在类似的情况下

if (condition)
    DLOG("foo");

尽管我的快速测试表明,在该行上生成的分号本身将用作条件内的无操作语句。

一无所有还是do {} while (0)更好?如果是这样,为什么?还有什么更好的吗?

4

3 回答 3

10

分号本身有两个缺点:

  • 您的宏的用户可以不用分号来编写它,编译器不会抱怨,并且
  • 一些编译器可能会发出关于可能杂散分号的警告。

do {} while (0)技巧解决了这两个问题:

DLOG("foo") // No semicolon

将触发错误,编译器不会警告您有关“杂散”分号的信息。

于 2012-07-18T19:57:19.260 回答
6

请参阅用于调试打印的 C#define 宏,以了解为什么需要不同形式的无操作。即使您不使用它,您也希望编译器解析调试打印代码,这样错误就不会蔓延。

于 2012-07-18T19:56:28.980 回答
0

if快速的答案是 do/while 方法可以让您进行多语句替换,并且在您遇到的问题中仍将其用作单个语句。对于单个表达式替换,我认为没有任何区别。

于 2012-07-18T19:55:46.227 回答