【@.1 可变形参个数函数】
C语言中,即使使用void*作为形参,也只能起到扩展形参类型的作用,而如果想要改变形参的个数呢?如果是C++的话就会很方便的通过函数的多态来实现这一功能,但是在C语言中实现起来就比较麻烦了。但并不是不可以实现,而是一般C编程没多少人用而已。考虑一个求平均数的函数,形参随便传入任意多个int类型的数,返回他们的平均值,用C语言应该怎么实现?这就需要用到可变形参个数的函数来实现了。
Variable Argument Lists, 在C语言中由stdarg.h头文件中定义了几个宏可以来做到这个事请。函数的形参无外乎是将他们以及函数的返回地址压入栈中,在运行时从栈中取出这些参数值,所以我们需要做的就是将传入的参数,不管有多少个,一个个从栈中找出来。
【@.2 求任意多个数的平均值函数】
float ave(int count,...) //Need to specify the count of vars
{
va_list valist;
float sum=0;
int i;
va_start(valist,count);
for(i=0;i<count;i++)
sum+=va_arg(valist, int);
va_end(valist);
return sum/count;
}
以上设计一个函数求任意多个数的平均值,注意到形参列表的第二个为"..."三个英文句号。
首先va_list就是头文件
printf("average:%f\n",ave(5, 1,2,3,7,9));
使用时可以直接想上面一样printf打印出来就可以看到结果,非常方便。再次注意,第一个参数我们用做后面待求平均数的个数传入函数的。
好这里就出现问题了,我随便输入了多少个参数之后,还一定得输入这些参数的个数,太麻烦了,有没有一种检查机制能自动帮我判断输入参数的个数呢?答案是,没有。就像上面说到的那样,用va_arg()宏弹出形参栈的时候的次数必须由程序员自己保证,所以有多少参数这个统计工作得由程序员自己做。好在,我们可以采用一些技巧来帮助我们完成这一任务,比如下面代码:
float average(int count,...) //Use an array to be the vars
{
va_list valist;
float sum=0;
int i;
int *array;
va_start(valist,count);
array=va_arg(valist, int*);
for(i=0;i<count;i++)
{
sum+=array[i];
printf("No.%2d:\t%d\n",i+1,array[i]);
}
va_end(valist);
return sum/count;
}
int main(void) {
int array[] = {5,7,9,11,13,15,20,22,16,11,-4,2,19};
float result = average(sizeof(array)/sizeof(int),array);
printf("Average: %f\n",result);
//printf("average:%f\n",ave(5, 1,2,3,7,9));
return EXIT_SUCCESS;
}
将想要求平均数的一组数放在int[]数组array里,使用时只需修改这个数组即可,参数的个数统计由sizeof函数就可以算出,比刚才方便多了。在统计函数里面采用va_arg时将形参作为一个int*弹出,再控制好大小一个个取出来即可。
【@.3 可变参数个数函数与C语言的多态】
C++语言的继承,封装,多态的特性完全可以结合C语言中的函数指针和结构体来完成。而可变参数个数的函数这种技巧也提供给我们用C的面向对象风格编程一条新的思路。比如这篇博客或者另一篇博客就提到了这一技巧,其中对象的实例化就用到了这里的可变参数函数技巧。
@.[FIN] @.date->Jan 4, 2013 @.author->apollius
原文链接: https://www.cnblogs.com/apollius/archive/2013/01/04/2845008.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/74465
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!