va_list、va_start、va_end
va(variable argument)函数,函数参数的个数可变。C/C++中提供给我们的va函数比较少,scanf()/printf()系列函数,exec()系列。由于va函数的参数不确定性,在实际应用中具有
很大的灵活性。
先从大家最熟悉的printf()说起。
printf的函数原型为:
- int printf(const char * 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上的内容
仅仅为了自己熟练,看完了之后自己又写篇,做个记号。