在实际编程中,有时候会遇到函数传参时事先不知道要传递几个参数,需要在程序执行时才能确定,在一定程度上也害苦了程序猿们。其实,在在C/C++中,已经定义了一个可用于传递变长参数列表的宏va_arg()。
首先,我们来看一个例子,然后再简单分析与va_arg宏相关的内容和细节。
#include <IOSTREAM> #include <STRING> #include <CSTDIO> #include <CSTDARG> using namespace std; int gSum( int,...); int main( int argc, char*argv[]) { int ans = gSum(4,5,6,7,1); cout<<"gSum(4,5,6,7,1)="<<ans<<endl; cin>>ans; return 0; } int gSum( int num,...) { int ans=0; va_list argptr; va_start(argptr,num); for (; num>0; num--) { ans +=va_arg(argptr,int); } va_end(argptr); return ans; }其中va_arg宏在CSTDARG库下,所以在程序开始前,要包含该库。程序执行的结果5+6+7+1=19如下:
通过上面程序执行的结果可以看到我们实现了可变长参数的函数求和,在该类程序中:
1)首先,必须调用va_start() 传递有效的参数列表va_list和函数强制的第一个参数。第一个参数代表将要传递的参数的个数。
2)其次,调用va_arg()传递参数列表va_list 和将被返回的参数的类型。va_arg()的返回值是当前的参数。
3)再次,对所有的参数重复调用va_arg()
4)最后,调用va_end()传递va_list对完成后的清除是必须的。
下面来看看va_start()、va_arg()以及 va_end()这三个函数的原型:
1)type va_arg( va_list argptr, type );
2)void va_end( va_list argptr );
3)void va_start( va_list argptr, last_parm );
其实,通过查看源文件可以知道,以上三个函数只是c里面定义的一些宏:
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
可变参数列表在实际编程中有很多应用,这里不再举例。