Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么';这不是我简单的C宏工作吗?_C_Macros_Preprocessor Directive - Fatal编程技术网

为什么';这不是我简单的C宏工作吗?

为什么';这不是我简单的C宏工作吗?,c,macros,preprocessor-directive,C,Macros,Preprocessor Directive,我想制作一个简单的宏,像这样调用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 valu

我想制作一个简单的宏,像这样调用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)
它正确地打印了第一部分“在sime_时间=…”,但后面部分显示“已处理的事件…”时,它错误地打印了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
只是
“处理的事件类型:%d,值为%f\n”
,第二个
printf()
调用只是为
%d
%f
提取垃圾,因为宏从不告诉它任何关于
id
data
的信息,所以它们永远不会传递到
printf()

你想要的是:

#define DEBUGPRINTF(msg, id, data) printf("At sim_time = %f:", sim_time); printf(msg, id, data);
if (showit)
    DEBUGPRINTF("hit the showit point -- showit=%d\n",showit);
或者,如果您需要更灵活的方法,可以使用可变宏。

使用双(嵌套)定义:

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

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

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

#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)
进行封装:

这允许您执行以下操作:

#define DEBUGPRINTF(msg, id, data) printf("At sim_time = %f:", sim_time); printf(msg, id, data);
if (showit)
    DEBUGPRINTF("hit the showit point -- showit=%d\n",showit);
因此,使用宏的代码不必知道它实际上是两条语句[或没有]


更新:

DEBUGPRINTF(msg…
不符合标准,但有一些旧式编译器扩展。你在省略号前漏掉了一个逗号

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

但是,以下是一些可能希望使用替代方法的资源:


  • @当然是保格里菲斯。对不起,我不习惯预处理器指令。出于某种原因,我将括号内的所有内容都映射到“msg”中。与此无关,但最好在多指令宏周围放上括号,如下所示:
    #define DEBUGPRINTF(msg,id,data){etch}
    。否则,当在
    if
    @user1320881:之后使用宏时,您可能会得到一些惊喜:这仍然会导致错误的代码,例如在
    if
    语句中。正确执行此操作的常用方法是将其包装为
    do。。而(0)
    虚拟循环。每个现代编译器都会识别这种模式并优化循环。@Olaf:在这种情况下,由于
    printf
    调用是表达式,所以最好用逗号运算符将它们分开,并将整个过程括在括号中(并去掉分号)。
    do。。。while(0)
    trick让我们在任何需要语句的地方使用宏,但是如果扩展是表达式,它就更灵活了。这只不过是OP已有的功能而已。它根本无法解决OP的实际问题。如果您按照OP的要求尝试
    DEBUGPRINTF(“已处理事件类型:%d,值为%f\n”,id,数据)
    ,则您会发现解决方案将以与OP所经历的完全相同的方式失败。如果
    之类的语句体使用
    DEBUGPRINTF(msg…
    不符合标准,则仍会导致问题,但是一些遗留的编译器扩展。你在省略号前漏掉了一个逗号。