为什么我的简单 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
提取垃圾,因为您的宏从不告诉它有关 id
或 data
的任何信息,因此它们永远不会传递给 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 多年。
但是,对于那些可能希望使用其他方式的人来说,这里有一些资源:
我想制作一个像这样调用 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
提取垃圾,因为您的宏从不告诉它有关 id
或 data
的任何信息,因此它们永远不会传递给 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 多年。
但是,对于那些可能希望使用其他方式的人来说,这里有一些资源: