试图创建一个宏,可以用于在定义debug时打印调试消息,就像下面的伪代码:

#define DEBUG 1
#define debug_print(args ...) if (DEBUG) fprintf(stderr, args)

这是如何用宏来完成的呢?


当前回答

根据http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html, __VA_ARGS__之前应该有##。

否则,宏#define dbg_print(format,…)printf(format, __VA_ARGS__)将不会编译以下示例:dbg_print("hello world");

其他回答

我使用的方法是这样的:

#ifdef DEBUG
 #define D if(1) 
#else
 #define D if(0) 
#endif

而我只是用D作为前缀:

D printf("x=%0.3f\n",x);

编译器看到调试代码,没有逗号的问题,它的工作无处不在。此外,当printf不够用时,比如当你必须转储一个数组或计算一些对程序本身是冗余的诊断值时,它也可以工作。

编辑:好的,它可能会产生一个问题,当附近有其他地方可以被这个注入的if拦截。下面是一个版本:

#ifdef DEBUG
 #define D 
#else
 #define D for(;0;)
#endif

这是我所使用的:

#if DBG
#include <stdio.h>
#define DBGPRINT printf
#else
#define DBGPRINT(...) /**/  
#endif

即使没有额外的参数,它也具有正确处理printf的好处。在DBG ==0的情况下,即使是最笨的编译器也没有什么可考虑的,因此不会生成任何代码。

#define PRINT_LOG(str_format, ...) { \
    time_t curtime=time (NULL); \
    struct tm *ltm = localtime (&curtime); \
    printf("[%d-%02d-%02d %02d:%02d:%02d] " str_format, \
        ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, \
        ltm->tm_hour, ltm->tm_min, ltm->tm_sec, ##__VA_ARGS__); \
}
    
PRINT_LOG("[%d] Serving client, str=%s, number=%d\n", getpid(), "my str", 10);

所以,当使用gcc时,我喜欢:

#define DBGI(expr) ({int g2rE3=expr; fprintf(stderr, "%s:%d:%s(): ""%s->%i\n", __FILE__,  __LINE__, __func__, #expr, g2rE3); g2rE3;})

因为它可以插入到代码中。

假设您正在尝试调试

printf("%i\n", (1*2*3*4*5*6));

720

然后你可以把它改成:

printf("%i\n", DBGI(1*2*3*4*5*6));

hello.c:86:main(): 1*2*3*4*5*6->720
720

你可以得到一个表达式被求值为什么的分析。

这样就避免了双重评估的问题,但缺少物理系统确实会导致名称冲突。

然而它是嵌套的:

DBGI(printf("%i\n", DBGI(1*2*3*4*5*6)));

hello.c:86:main(): 1*2*3*4*5*6->720
720
hello.c:86:main(): printf("%i\n", DBGI(1*2*3*4*5*6))->4

所以我认为,只要避免使用g2rE3作为变量名,就可以了。

当然,我发现它(以及字符串的联合版本,以及调试级别的版本等)非常宝贵。

我相信这个主题的变化提供了调试类别,而不需要每个类别有一个单独的宏名称。

我在Arduino项目中使用了这个变体,其中程序空间限制为32K,动态内存限制为2K。添加调试语句和跟踪调试字符串很快就会占用空间。因此,在每次构建代码时,必须能够将编译时包含的调试跟踪限制在必要的最低限度。

debug.h

#ifndef DEBUG_H
#define DEBUG_H

#define PRINT(DEBUG_CATEGORY, VALUE)  do { if (DEBUG_CATEGORY & DEBUG_MASK) Serial.print(VALUE);} while (0);

#endif

调用.cpp文件

#define DEBUG_MASK 0x06
#include "Debug.h"

...
PRINT(4, "Time out error,\t");
...