用宏重新定义printf(debug),宏函数中的可变参数

1.用宏重新定义printf(debug)

可以这样定义宏:

#include <stdio.h>
//#define NDEBUG 10
#ifdef NDEBUG
#define debug_printf(fmt, ...)
#else
extern int debug_print;
#define debug_printf(fmt, ...) ({ 
    if(debug_print) 
    {               
        printf(fmt, ##__VA_ARGS__);
    } 
 })
#endif
int main(void) {
          
    
    int debug_print=1;
	debug_printf("test%d",1,23);
	return 0;
}

输出:

test1

当我们不想让main函数中的debug_printf生效,且不删除main函数中的debug_printf()时,那么就需要定义NDEBUG,如果不定义就会报如下函数没有定义的错误,如果定义了,那么根据#if NDEBUG下只定义宏名,没有宏函数体,展开时就没有东西,但编译不会报错。

#include <stdio.h>
//#define NDEBUG 1
#ifdef NDEBUG
#define debug_printf(fmt, ...)//只定义宏名,没有宏函数体,展开时就没有东西
#else
extern int debug_print;
#define debug_printf(fmt, ...) ({ 
    if(debug_print) 
    {               
        printf(fmt, ##__VA_ARGS__);
    } 
 })
#endif
int main(void) {
          
    
    //int debug_print=1;
	debug_printf("test%d",1,23);
	return 0;
}

输出:

Compilation Failed


/usr/bin/ld: /tmp/ccXdjenI.o: in function `main:
file.cpp:(.text+0x6): undefined reference to `debug_print
collect2: error: ld returned 1 exit status

2.宏函数中的可变参数

#define debug_printf(fmt, ...) ({ 
    if(debug_print) 
    {               
        printf(fmt, __VA_ARGS__);
    } 
 })

”…”表示可变参数。在宏的调用中,它会展开为…位置处传入的所有字符,数字,包括逗号,并替换掉宏体中的__VA_ARGS__,注意fmt, ##__VA_ARGS__之间的“,”也会展开。所以当没有参数传入时,比如 debug_printf(“hello world”) 上面会展开成:

{
          
    
    if(debug_print) 
    {
          
                  
        printf("hello world",);
    } 
 }

那么就多了一个“,”会报错。

所以就有了在__VA_ARGS__前加##,目的是,当省略可变参数时,”##”会使得预编译器删除它前面的逗号,提供可变参数时,”##”不起作用。

也可以指定可变参数名称:

#define debug_printf(fmt, chm...) ({ 
    if(debug_print) 
    {               
        printf(fmt, ##chm);
    } 
 })

chm可以替换成其他。

经验分享 程序员 微信小程序 职场和发展