1. 调试功能一般会使用到宏+可变参数的方式
1.1
##__VA_ARGS__ 之详细解析
例如:
case A.
#define my_print1(...) printf(__VA_ARGS__)
my_print1("i=%d,j=%d\n",i,j) 正确打印
case B.
#define my_print2(fmt,...) printf(fmt, __VA_ARGS__)
my_print1("i=%d,j=%d\n",i,j)
正确打印
my_print2("iiiiiii\n")
编译失败,因为扩展出来只有一个参数,至少要两个及以上参数
case C.
#define my_print2(fmt,...) printf(fmt, ##__VA_ARGS__)
my_print1里面不管是几个参数都能正确打印
宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错
#define MODULE_NAME "MY_LIBS"
#define log_e(fmt, ...) printf("[ERROR]["MODULE_NAME"](%s|%d)"fmt,__func__,__LINE__,##__VA_ARGS__)
#include <stdio.h> #define MODULE_NAME "MY_LIBS" #define log_e(fmt, ...) printf("[ERROR]["MODULE_NAME"](%s|%d)"fmt,__func__,__LINE__, ##__VA_ARGS__) int main(){ int i = 1111; log_e("hello : i=%d\n", i); return 0; }
root@lmw-virtual-machine:/home/lmw/桌面/C_Text#
root@lmw-virtual-machine:/home/lmw/桌面/C_Text# gcc my_log.c -o ab
root@lmw-virtual-machine:/home/lmw/桌面/C_Text#
root@lmw-virtual-machine:/home/lmw/桌面/C_Text# ./ab
[ERROR][MY_LIBS](main|14)hello : i=1111
root@lmw-virtual-machine:/home/lmw/桌面/C_Text#
1.2
#include <iostream> #include <stdio.h>
using namespace std; #define Debug( fmt2, arg12... ) \
do{ printf("%s, %s %s\n", fmt2, ##arg12); \ // 这里有两个%s对应##arg12,所以就会打印出可变参数中的两个参数"what" 和"nice"
printf("***************[%s-%s-%d]: "fmt2 , __FILE__, __FUNCTION__, __LINE__, ##arg12); \ }while(0); int main(){ Debug("hi %s %s \n", "what", "nice"); // 针对这条打印进行分析
return 0; } // 实测,第二条打印语句内的 "hi %s %s \n" 就是fmt2。 // 而"what", "nice"是不定参数##arg12的值
第二条打印语句分析: "hi %s %s \n"就是fmt2。 而"what", "nice"是不定参数##arg12的值。
需要注意的是: 如果只有1个%s格式符对应##arg12,那么只会打印出第一个"what",如果有两个格式符,那么则会打印出两个可变参数。
代码运行结果:
2. 编写一些功能函数的时候,我们也会用到可变参数
C++代码示例:
string combine_devtypes(int num, ...){ string ret, tmp; va_list valist; char* str = NULL; int i; /* 为 num 个参数初始化 valist */ va_start(valist, num); /* 访问所有赋给 valist 的参数 */
for (i = 0; i < num; i++) { str = va_arg(valist, char*); tmp = str; ret += tmp; if(i < num-1){ tmp = " "; ret += tmp; } } /* 清理为 valist 保留的内存 */ va_end(valist); return ret; }
本例子的函数功能是拼接字符串,并且在中间加上一个空字符。
调用方式: string obj = combine_devtypes(2, "hello", "boy") , 得到的是包含"hello boy"信息的这么一个字符串。
.