类似这样的函数定义:printf(char *fmt, ...)
示例:
自定义一个可变函数:Func(char *s,char *fmt, ...)
特点是函数必须有一个char*fmt作为变量,它一般用在可变参数的前一个参数,根据这个变量计算出后续参数的地址或值
它们其实是将传入的参数作为相连的内存空间,传递进入函数。
fmt则规定了后续变量。
int,float,char类型则是传值
char*则是传地址
在内存的排列方式: s,fmt,第一个参数,第二个参数 ......
_tprintf(_T("%s %d"),_T("dddd"),1234);
因此,可以利用以下几个宏定义,将各个参数按照各自的方式取出
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //初始化为第一个可选参数地址,v一般用变参数的前一个定参数
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址
#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
用法:
{
va_list pArgList;
va_start(pArgList, f_buf);
//循环处理
//循环fmt,取值用va_arg(pArgList,t),其中t是参数类型,每一次取值,pArgList都将自动移动到下一个变量地址
//如果是整形数 int num=va_arg(pArgList,int);
//如果是字符串 char *p=(char*)va_arg(pArgList,int);
//...执行自己的操作.
//循环结束
va_end(pArgList);
}
一般来说使用不定参数作为函数,一般是为了二次调用系统原有函数或者组装字符串使用.
如果是为了组装字符串使用,C++提供了二次组装字符串的方法:_vstprintf();
代码示例:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
int Func(TCHAR *src,TCHAR * f_buf, ...)
{
va_list pArgList;
va_start(pArgList, f_buf);
_vstprintf(src,f_buf,pArgList);
va_end(pArgList);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR buf[100];ZeroMemory(buf,100);
Func(buf,_T("%d%c%.3f%s"),123,'a',1.5678,_T("DDDD"));
cout<<buf<<endl;
return 0;
}
如果为了再次调用系统函数:
调用系统函数_vtprintf()示例:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
int Func(TCHAR *src,TCHAR * f_buf, ...)
{
va_list pArgList;
va_start(pArgList, f_buf);
_vtprintf(f_buf,pArgList);
va_end(pArgList);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR buf[100];ZeroMemory(buf,100);
Func(buf,_T("%d%c%.3f%s"),123,'a',1.5678,_T("DDDD"));
cout<<buf<<endl;
return 0;
}
//注意_vtprintf 与_tpritf的的参数类型的区别!!!!!!!!!!!!!!!!!!!!!