在调试过程中,我们经常会自定义打印,比如日志信息的输出,这时就会用VA_ARGS
,接下来详细讲解!
__VA_ARGS__是C语言设定的一个预定义宏,用于处理可变参数的参数列表。通常用在宏定义中,以便宏可以接收不定数量的参数,并将他们作为整体处理。
通常的函数参数列表都是固定的,但也存在着不定参数数量的函数,如:printf
,为了定义可以处理不同参数个数的宏,
C99标准引入了 VA_ARGS
,下列的代码均在C99及C99以上标准的环境下运行。
__VA_ARGS__表示所有在宏调用中传递的额外参数。它可以放在宏定义的参数列表的末尾,用于接收任意数量的额外参数,比如:
#define LOG_DEBUG(format,...) printf(format,__VA_ARGS__)
解析:
#define LOG_(format,...) printf("[%s:%d]"format"\n",__FILE__,__LINE__,__VA_ARGS__);
如上的代码就是对日志定义的一个宏。
##VA_ARGS
大家在了解__VA_ARGS__时,一定会看到有些地方在该宏定义前使用 ## 运算符来处理可变参数,如:
#define DEBUG_LOG(fmt, ...) \
printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
##__VA_ARGS__前面加上##的作用是:当可变参数的个数为0时,这里的##可以把把前面多余的","去掉,
否则会编译出错。
当想要在自定义的调试信息加上时间、行数等信息时,应该怎么做呢?先把正确的用法写在前面:
#include
#define LOG3(fmt, ...) printf("<%s:%s>:"fmt"\r\n", __FILE__, __FUNCTION__, ##__VA_ARGS__)
int main(int argc, char** argv)
{
char *str = "test __VA_ARGS__";
int num = 10086;
LOG3("this is test __VA_ARGS__");
LOG3("this is test __VA_ARGS__:%s, %d", str, num);
LOG3();
return 0;
}
结果为:
<main.c:main>:this is test __VA_ARGS__
<main.c:main>:this is test __VA_ARGS__:test __VA_ARGS__, 10086
<main.c:main>:
但是如果不加##
:可变参数为空时,报错。
#include
#define LOG2(fmt, ...) printf("<%s:%s>:"fmt"\r\n", __FILE__, __FUNCTION__, __VA_ARGS__)
int main(int argc, char** argv)
{
LOG2();//不传参数,编译报错
LOG2("this is test __VA_ARGS__");//编译报错
LOG2("this is test __VA_ARGS__:%s, %d", str, num);//正常编译
return 0;
}
分析: