va_list、va_start、va_end

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

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





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值