试图创建一个宏,可以用于在定义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");

其他回答

对于一个可移植的(ISO C90)实现,您可以使用双括号,就像这样;

#include <stdio.h>
#include <stdarg.h>

#ifndef NDEBUG
#  define debug_print(msg) stderr_printf msg
#else
#  define debug_print(msg) (void)0
#endif

void
stderr_printf(const char *fmt, ...)
{
  va_list ap;
  va_start(ap, fmt);
  vfprintf(stderr, fmt, ap);
  va_end(ap);
}

int
main(int argc, char *argv[])
{
  debug_print(("argv[0] is %s, argc is %d\n", argv[0], argc));
  return 0;
}

或者(不推荐)

#include <stdio.h>

#define _ ,
#ifndef NDEBUG
#  define debug_print(msg) fprintf(stderr, msg)
#else
#  define debug_print(msg) (void)0
#endif

int
main(int argc, char *argv[])
{
  debug_print("argv[0] is %s, argc is %d"_ argv[0] _ argc);
  return 0;
}

下面是我使用的版本:

#ifdef NDEBUG
#define Dprintf(FORMAT, ...) ((void)0)
#define Dputs(MSG) ((void)0)
#else
#define Dprintf(FORMAT, ...) \
    fprintf(stderr, "%s() in %s, line %i: " FORMAT "\n", \
        __func__, __FILE__, __LINE__, __VA_ARGS__)
#define Dputs(MSG) Dprintf("%s", MSG)
#endif
#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);

我使用的方法是这样的:

#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的情况下,即使是最笨的编译器也没有什么可考虑的,因此不会生成任何代码。