众所周知,C中有这么一族函数,其参数个数并不是固定的,对于初学者而言经常接触到 的最可能的就数printf,scanf之流了,今天就这篇文章简单探讨下可变参数的实现原理(不准备对printf之类的函数进行解剖,这涉及到繁琐的格式字符串的分解和解析,超出了今天话题的内容). 要实现可变参数列,需要用到C语言定义中的一些特定的数据类型和宏,这些内容包含在 头文件
stdarg.h中,下面通过本人的学习对就如何实现可变参数函数进行详细的说明,下面给出一个实现可变参数函数的模板: return_type func_name(par_type last,...)
{
//...............
va_list argPtr;//定义一个自变量指针以访问...参数列表
va_start(argPtr,last);//使用最后一个强制性参数的位置初始化这个参数指针表
//...............
type-base data;//声明一个基本数据类型
data=va_arg(argPtr,type-base);//从...参数列中获取当前所引用的类型值
//.........
va_end(argPtr);//结束对可选自变量列表的访问
return return_type_value;
}
在C中实现可变参数函数以上的模板是一个基本的流程,下面进行下说明(参考《C语言核心技术》,《精通UNIX下C语言编程与项目实践》) void va_start(va_list argPtr,last);
va_start使用第一个可选自变量的位置来初始化argPtr自变量指针.此宏的第二个自变量必须是"此函数最后一个有名称的参数",开始使用可选性自变量之前,必须显示调用这个宏做初始化工作.
type va_arg(va_list argPtr,type);
va_arg宏能够获取到当前argPtr所引用的可选性自变量,将值作为第二个type而返回,其间它的一个重要工作就是将argPtr引用的位置移到下一个将要访问的可选自变量(大有后缀++之势);
void va_end(va_list argPtr);
当不在需要自变量指针时,必须调用va_end宏,如果想使用va_start或va_copy来重新初始化一个之前用过的可变参的自变量指针,也必须先调用此宏.
void va_copy(va_list dest,va_list src);
va_copy宏使用目前的src来初始化自变量指针dest,而后就可以使用dest从src的位置存取可选性自变量列表.
下面实现mul与add的可变参数函数 #include <stdarg.h>
double mul(int n,...)
{
va_list argptr;
va_start(argptr,n);
double result=1.0;
int i=0;
for(;i<n;++i)
result*=va_arg(argptr,double);
va_end(argptr);
return result;
}
double add(int n,...)
{
int i=0;
double sum=0.0;
va_list argptr;
va_start(argptr,n);
for(;i<n;++i)
sum+=va_arg(argptr,double);
va_end(argptr);
return sum;
}
int main(void)
{
printf("2*3*10=%f\n",mul(3,2.0,3.0,10.0));
printf("10*34=%f\n",mul(2,10.0,34.0));
printf("sum(10,20)=%f\n",add(2,10.0,20.0));
return 0;
}