本文主要介绍可变参数 函数的实现方法。
头文件:#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');