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

时间:2016-04-02 21:23:35

标签: c macros preprocessor-directive

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

width

现在我打电话

height

它打印第一部分"在sime_time = ..."正确,但后面的部分,它说"处理事件......"不正确地打印id和数据的值。

同时

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

这样可以正确打印所有内容!那么为什么我的宏不评估呢?

3 个答案:

答案 0 :(得分:2)

你声明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);

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

答案 1 :(得分:2)

因为您希望并且正在使用常规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);

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

<强>更新

  

DEBUGPRINTF(msg...)不符合标准,但是一些遗留的编译器扩展。你在省略号之前错过了一个逗号。

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

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

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

答案 2 :(得分:-3)

使用双(嵌套)定义:

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

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