为什么我的简单 C 宏不起作用?

Why doesn't my simple C macro work?

我想制作一个像这样调用 printf() 两次的简单宏

#ifdef ENABLE_DEBUGPRINTF
#define DEBUGPRINTF(msg) printf("At sim_time = %f:", sim_time); printf(msg);
#else
#define DEBUGPRINTF(msg)  //evalutes to nothing
#endif

现在打电话的时候

DEBUGPRINTF("Processed event type: %d with value %f\n", id, data)

它正确地打印了第一部分 "At sime_time = ... ",但它说的后一部分 "Processed events ... " 错误地打印了 id 和数据的值。

同时

printf("Processed event type: %d with value %f\n", id, data);

正确打印值。

当我尝试通过准确写出我认为宏的计算结果来执行它时,我有。

printf("At sim_time = %f:", sim_time); printf("Processed event type: %d with value %f\n", id, data);

这会正确打印所有内容!那么为什么我的宏没有对此进行评估?

您声明 DEBUGPRINTF 接受一个参数,但随后将其传递给三个参数,因此它当然不会像您预期的那样工作。

msg 在您的第一个示例中只是 "Processed event type: %d with value %f\n",而您的第二个 printf() 调用只是为 %d%f 提取垃圾,因为您的宏从不告诉它有关 iddata 的任何信息,因此它们永远不会传递给 printf().

你想要这样的东西:

#define DEBUGPRINTF(msg, id, data) printf("At sim_time = %f:", sim_time); printf(msg, id, data);

或者,如果您需要更灵活的东西,可以使用可变参数宏。

使用双重(嵌套)定义:

#define FIRST         printf("…")
#define DEBUGMSG(msg) FIRST;printf(msg)

定义中有一个参数,实现中有一个参数。

因为您想要并且正在使用常规 printf 的全部灵活性,所以您想要的是带有 variadic 参数的宏:

#ifdef ENABLE_DEBUGPRINTF
#define DEBUGPRINTF(msg...) \
    printf("At sim_time = %f:", sim_time); printf(msg);
#else
#define DEBUGPRINTF(msg...)  /*evalutes to nothing*/
#endif

我以前做过很多次,我建议用 do { } while (0):

封装
#ifdef ENABLE_DEBUGPRINTF
#define DEBUGPRINTF(msg...) \
    do { \
        printf("At sim_time = %f:", sim_time); \
        printf(msg); \
    } while (0)
#else
#define DEBUGPRINTF(msg...)  //evalutes to nothing
#endif

这使您可以执行以下操作:

if (showit)
    DEBUGPRINTF("hit the showit point -- showit=%d\n",showit);

因此,使用宏的代码不必知道它实际上是两个语句[或none]


更新:

DEBUGPRINTF(msg...) is not standard compliant, but some legacy compiler extension. You missed a comma before the ellipsis.

也许吧,但就我个人而言,我仍然更喜欢它,并且已经在生产代码中使用了 10 多年。

但是,对于那些可能希望使用其他方式的人来说,这里有一些资源:

  1. https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
  2. https://en.wikipedia.org/wiki/Variadic_macro