本文主要介绍可变参数 函数的实现方法。
头文件:#include <stdarg.h>
一、函数系列介绍
1、va_start函数
原型:void va_start(va_list ap, last);
ap:va_list 类型的变量,指向参数的指针
last:最后一个显式声明的参数,以用来获取第一个变长参数的位置
2、va_arg函数
原型:type va_arg(va_list ap, type);
ap:va_list 类型的变量,指向参数的指针
type:指要获取的参数的类型
3、va_end函数
原型:void va_end(va_list ap);
ap:va_list 类型的变量,指向参数的指针
4、va_copy函数
原型:void va_copy(va_list dest, va_list src);
二、函数详细介绍
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap) ( ap = (va_list)0 )
三、使用步骤介绍
1)定义一个va_list类型的变量,变量是指向参数的指针;
2)va_start初始化刚定义的变量,第二个参数是最后一个显式声明的参数;
3)va_arg返回变长参数的值,第二个参数是该变长参数的类型;
4)va_end将a)定义的变量重置为NULL。
四、示例
示例1:
void test_printf2(int num,...)
{
va_list args;
int i = 0;
va_start(args,num);
for(i; i < num; i++)
printf("%d\n", va_arg(args, int));
va_end(args);
}
test_printf2(3,1,2,3);
示例2:
void test_printf6(char *headData, char *format,...)
{
char buff[4096];
va_list args;
memcpy(buff, headData, strlen(headData));
va_start(args, format);
vsnprintf(buff+strlen(headData), 1024, format, args);
va_end(args);
printf("%s\n", buff);
}
test_printf6("requestData", "len is %d, data is %s", 10, "helloworld");
示例3:
void test_printf7(char *format,...)
{
int tmpLen;
char *buff, *buf, *ptr;
va_list args;
buff = (char *) malloc(sizeof(char)*1024);
buf = buff;
va_start(args, format);
for (ptr = format; *ptr; ptr++) {
if(*ptr == '%') {
switch (*(++ptr)) {
case 'd':
*buff++ = va_arg(args, int) + 0x30;
break;
case 's':
tmpLen = va_arg(args, int);
memcpy(buff, va_arg(args, char *), tmpLen);
buff += tmpLen;
break;
case 'c':
*buff++ = va_arg(args, int);
break;
}
} else{
printf("%c\n", *ptr);
}
}
*buff = '\0';
printf("%s\n", buf);//此处需注意打印要从头指针开始
va_end(args);
free(buf);//此处需注意释放的是头指针,否则会出现下面的错误
buf = NULL;
}
test_printf7("%d%d%s%c", 1,2,4,"helloWorld", 'E');
*** Error in `./a.out’: munmap_chunk(): invalid pointer: 0x0000000000e00047 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7f982c4fa725]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7f982c506c18]
./a.out[0x401575]
./a.out[0x4015c8]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f982c4a3830]
./a.out[0x4006d9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:01 919832 /home/zx/test/a.out
00601000-00602000 r–p 00001000 08:01 919832 /home/zx/test/a.out
00602000-00603000 rw-p 00002000 08:01 919832 /home/zx/test/a.out
00e00000-00e21000 rw-p 00000000 00:00 0 [heap]
7f982c26d000-7f982c283000 r-xp 00000000 08:01 792176 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f982c283000-7f982c482000 —p 00016000 08:01 792176 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f982c482000-7f982c483000 rw-p 00015000 08:01 792176 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f982c483000-7f982c643000 r-xp 00000000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c643000-7f982c842000 —p 001c0000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c842000-7f982c846000 r–p 001bf000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c846000-7f982c848000 rw-p 001c3000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c848000-7f982c84c000 rw-p 00000000 00:00 0
7f982c84c000-7f982c872000 r-xp 00000000 08:01 792110 /lib/x86_64-linux-gnu/ld-2.23.so
7f982ca56000-7f982ca59000 rw-p 00000000 00:00 0
7f982ca6e000-7f982ca71000 rw-p 00000000 00:00 0
7f982ca71000-7f982ca72000 r–p 00025000 08:01 792110 /lib/x86_64-linux-gnu/ld-2.23.so
7f982ca72000-7f982ca73000 rw-p 00026000 08:01 792110 /lib/x86_64-linux-gnu/ld-2.23.so
7f982ca73000-7f982ca74000 rw-p 00000000 00:00 0
7ffe93f65000-7ffe93f86000 rw-p 00000000 00:00 0 [stack]
7ffe93ff0000-7ffe93ff2000 r–p 00000000 00:00 0 [vvar]
7ffe93ff2000-7ffe93ff4000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
示例4:
void test_printf5(char *data, char *format,...)
{
char buff[1024];
char *tmpBuff, *ptr;
va_list args;
int tmpLen = 0;
tmpBuff = buff;
memset(tmpBuff, 0x00, sizeof(buff));
memcpy(tmpBuff, data, strlen(data));
tmpBuff += strlen(data);
va_start(args, format);
for(ptr = format; *ptr; ptr++) {
switch (*ptr) {
case 'd':
*tmpBuff++ = va_arg(args, int) + 0x30;
break;
case 's':
tmpLen = va_arg(args, int);
*tmpBuff++ = tmpLen + 0x30;
memcpy(tmpBuff, va_arg(args, char *), tmpLen);
tmpBuff += tmpLen;
break;
case 'c':
*tmpBuff++ = va_arg(args, int);
break;
}
}
va_end(args);
*tmpBuff = '\0';
printf("%s\n", buff);
return ;
}
test_printf5("reqeustData", "dcdsdsc",2,'A',3,4,"buffer",5,3,"heloo",'C');