va(variable argument)函数,函数参数的个数可变。C/C++中提供给我们的va函数比较少,scanf()/printf()系列函数,exec()系列。由于va函数的参数不确定性,在实际应用中具有
很大的灵活性。
先从大家最熟悉的printf()说起。
printf的函数原型为:
int printf(const char * szFormat,...);szFormat表示用来格式化参数的信息,“...”表示可选参数,可有可无,根据实际情况而定。
系统提供一系列的vprintf函数用于程序员封装自己的可变参数I/O函数。
vprintf/vscanf由于封装自己的标准输出/输入函数。
vfprintf/vfscanf用于封装自己的文件输出/输入。
vsprintf/vsscanf用于封装自己的格式化字符串函数。
但是以上函数会产生缓冲区溢出,建议采用以下函数替代:
_vsnprintf/_vsnscanf由于封装自己的标准输出/输入函数。
_vsntprintf/vsntscanf用于封装自己的格式化字符串函数。
// 例1:格式化到一个文件流,可用于日志文件 FILE *logfile; int WriteLog(const char * szFormat, ...) { va_list arg_ptr; va_start(arg_ptr, szFormat); int nWrittenBytes = vfprintf(logfile, szFormat, arg_ptr); va_end(arg_ptr); return nWrittenBytes; } … // 调用时,与使用printf()没有区别。 WriteLog("%04d-%02d-%02d %02d:%02d:%02d %s/%04d logged out.", nYear, nMonth, nDay, nHour, nMinute, szUserName, nUserID);
//例2格式化messagebox #include <windows.h> #include <tchar.h> #include <stdio.h> int MessageBoxPrint(TCHAR *szCaption,TCHAR *szFormat,...) { TCHAR szBuffer[1024]; va_list pArgList; va_start(pArgList,szFormat); _vsntprintf(szBuffer,sizeof(szBuffer)/sizeof(TCHAR),szFormat,pArgList); vfprintf va_end(pArgList); return MessageBox(NULL,szBuffer,szCaption,MB_OK); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int nShowCmd) { int cxScreen,cyScreen; cxScreen = GetSystemMetrics(SM_CXSCREEN); cyScreen = GetSystemMetrics(SM_CYSCREEN); MessageBoxPrint(TEXT("ScrnSize"),TEXT("The screen is %d pixels wide by %d pixels high."), cxScreen,cyScreen); return 0; }
#include<stdarg.h> #include <stdio.h> int Sum(int n,...) { int sum = 0; int tmp = 0; tmp = n; va_list va_ptr; va_start(va_ptr,n); while (tmp > 0) { sum += tmp; tmp =va_arg(va_ptr,int); } va_end(va_ptr); return sum; } int main() { int sum = Sum(1,2,3,-1); printf("%d\n",sum); return 0; }
1.va_list 指向一个个数可变参数列表指针
2.va_start (va_ptr,szFormat)指向个数可变参数列表的的第一个参数
3.va_arg(va_ptr,type) 返回当前的参数的type类型,并将va_ptr指针移植下一个参数。
4.va_copy(dest,src)从src拷贝一个个数可变参数列表到dest
5.va_end(va_ptr)清空参数列表,并将va_ptr置无效
注:指针参数被置无效后,可以通过va_start或va_copy恢复,但每调用一个va_start/va_copy,必须有相应的va_end与之匹配
文章参考:http://www.cnblogs.com/BloodAndBone/archive/2011/01/18/1938053.html
应该说全部是http://www.cnblogs.com/BloodAndBone/archive/2011/01/18/1938053.html上的内容
仅仅为了自己熟练,看完了之后自己又写篇,做个记号。