va_list、va_start、va_end(用于实现函数参数的个数可变的函数,如scanf()/printf()系列函数)

va_list、va_start、va_end

分类: C语言 C++ 402人阅读 评论(0) 收藏 举报
list winapi null file

va(variable argument)函数,函数参数的个数可变。C/C++中提供给我们的va函数比较少,scanf()/printf()系列函数,exec()系列。由于va函数的参数不确定性,在实际应用中具有

很大的灵活性。

先从大家最熟悉的printf()说起。

printf的函数原型为:

[cpp] view plain copy
  1. int printf(const char * szFormat,...);  
szFormat表示用来格式化参数的信息,“...”表示可选参数,可有可无,根据实际情况而定。

系统提供一系列的vprintf函数用于程序员封装自己的可变参数I/O函数。

vprintf/vscanf由于封装自己的标准输出/输入函数。

vfprintf/vfscanf用于封装自己的文件输出/输入。

vsprintf/vsscanf用于封装自己的格式化字符串函数。

但是以上函数会产生缓冲区溢出,建议采用以下函数替代:

_vsnprintf/_vsnscanf由于封装自己的标准输出/输入函数。

_vsntprintf/vsntscanf用于封装自己的格式化字符串函数。

[cpp] view plain copy
  1. // 例1:格式化到一个文件流,可用于日志文件  
  2.   FILE *logfile;  
  3.   int WriteLog(const char * szFormat, ...)  
  4.  {  
  5.  va_list arg_ptr;  
  6.  va_start(arg_ptr, szFormat);  
  7.   int nWrittenBytes = vfprintf(logfile, szFormat, arg_ptr);  
  8.  va_end(arg_ptr);  
  9.   return nWrittenBytes;  
  10.  }  
  11.  …  
  12.   // 调用时,与使用printf()没有区别。  
  13.   WriteLog("%04d-%02d-%02d %02d:%02d:%02d  %s/%04d logged out.",  
  14.  nYear, nMonth, nDay, nHour, nMinute, szUserName, nUserID);  

[cpp] view plain copy
  1. //例2格式化messagebox  
  2. #include <windows.h>  
  3. #include <tchar.h>  
  4. #include <stdio.h>  
  5.   
  6.   
  7. int MessageBoxPrint(TCHAR *szCaption,TCHAR *szFormat,...)  
  8. {  
  9.     TCHAR szBuffer[1024];  
  10.     va_list pArgList;  
  11.     va_start(pArgList,szFormat);  
  12.     _vsntprintf(szBuffer,sizeof(szBuffer)/sizeof(TCHAR),szFormat,pArgList);  
  13.     vfprintf  
  14.     va_end(pArgList);  
  15.       
  16.     return MessageBox(NULL,szBuffer,szCaption,MB_OK);  
  17.       
  18. }  
  19.   
  20. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int nShowCmd)  
  21. {  
  22.     int cxScreen,cyScreen;  
  23.     cxScreen = GetSystemMetrics(SM_CXSCREEN);  
  24.     cyScreen = GetSystemMetrics(SM_CYSCREEN);  
  25.     MessageBoxPrint(TEXT("ScrnSize"),TEXT("The screen is %d pixels wide by %d pixels high."),  
  26.         cxScreen,cyScreen);  
  27.     return 0;  
  28. }  


求任意个自然数的和:
[cpp] view plain copy
  1. #include<stdarg.h>  
  2. #include <stdio.h>  
  3.   
  4. int Sum(int n,...)  
  5. {  
  6.     int sum = 0;  
  7.     int tmp = 0;  
  8.     tmp = n;  
  9.     va_list va_ptr;  
  10.     va_start(va_ptr,n);  
  11.     while (tmp > 0)  
  12.     {  
  13.         sum += tmp;  
  14.         tmp =va_arg(va_ptr,int);  
  15.     }  
  16.     va_end(va_ptr);  
  17.     return sum;  
  18. }  
  19. int main()  
  20. {  
  21.     int sum = Sum(1,2,3,-1);  
  22.     printf("%d\n",sum);  
  23.     return 0;  
  24. }  

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上的内容

仅仅为了自己熟练,看完了之后自己又写篇,做个记号。

你可能感兴趣的:(C++,C语言)