码迷,mamicode.com
首页 > 编程语言 > 详细

c语言的可变参数实例

时间:2019-11-16 14:26:06      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:整数   必须   第一个   standard   存储   div   定义   argc   argv   

可变参数函数实现的步骤如下:

  • 1.在函数中创建一个va_list类型变量

  • 2.使用va_start对其进行初始化

  • 3.使用va_arg访问参数值

  • 4.使用va_end完成清理工作

接下来我们来实现一个变长参数函数来对给定的一组整数进行求和。程序清单如下:



#include <stdio.h> /*要使用变长参数的宏,需要包含下面的头文件*/ #include <stdarg.h> /* * getSum:用于计算一组整数的和 * num:整数的数量 * * */ int getSum(int num, ...) { va_list ap;//定义参数列表变量 int sum = 0; int loop = 0; va_start(ap, num); /*遍历参数值*/ for (; loop < num ; loop++) { /*取出并加上下一个参数值*/ sum += va_arg(ap, int); } va_end(ap); return sum; } int main(int argc, char *argv[]) { int sum = 0; sum = getSum(5, 1, 2, 3, 4, 5); printf("%d\n", sum); return 0; }

  上面的小程序接受变长参数,第一个参数表明将要计算和的整数个数,后面的参数是要计算的值。
编译运行可得结果:15。

 

总结

通过前面的分析和示例,我们来做一些总结

    • 变长参数实现的基本原理
      对于x86来说,函数参数入栈顺序为从右往左,因此,在知道第一个参数地址之后,我们能够通过地址偏移获取其他参数,虽然x86-64在实现上略有不同,但`对于开发者使用来说,实现变长参数函数没有32位和64位的区别。

    • 变长参数实现注意事项
      1.…前的参数可以有1个或多个,但前一个必须是确定类型。
      2.传入参数会可能会出现类型提升。
      3.va_arg的type类型不能是char,short int,float等类型,否则取值不正确,原因为第2点。
      4.va_arg不能往回取参数,但可以使用va_copy拷贝va_list,以备后用。
      5.变长参数类型注意做好检查,例如可以采用printf的占位符方式等等。
      6.即便printf有类型检查,但也要注意参数匹配,例如,将int类型匹配%s打印,将会出现严重问题。
      7.当传入参数个数少于使用的个数时,可能会出现严重问题,当传入参数大于使用的个数时,多出的参数不会被处理使用。
      8.注意字节对齐问题。

变长参数实现

经过前面的理解分析,我们知道,正是由于参数从右往左入栈(但是要注意的是,对于x86-64,它的参数不是完全从右往左入栈,且参数可能不在一个连续的区域中,它的变长参数实现也更为复杂,我们这里不展开)可以实现变长参数。当然了,这一切,C已经有现成可用的一些东西来帮我们实现变长参数。
它主要通过一个类型(va_list)和三个宏(va_start、va_arg、va_end)来实现

va_list :存储参数的类型信息,32位和64位实现不一样。
void va_start ( va_list ap, paramN );
参数:
ap: 可变参数列表地址 
paramN: 确定的参数
功能:初始化可变参数列表,会把paraN之后的参数放入ap中

type va_arg ( va_list ap, type );
功能:返回下一个参数的值。

void va_end ( va_list ap );
功能:完成清理工作。
转载自:
https://mp.weixin.qq.com/s/CbXT6G0CHzp0BG0gS-hprw

#include <stdio.h>
#include <stdarg.h>
#include <math.h>

double sample_stddev(int count, ...)
{
    /* Compute the mean with args1. */
    double sum = 0;
    va_list args1;
    va_start(args1, count);
    va_list args2;
    va_copy(args2, args1);   /* copy va_list object */
    for (int i = 0; i < count; ++i)
    {
        double num = va_arg(args1, double);
        sum += num;
    }
    va_end(args1);
    double mean = sum / count;

    /* Compute standard deviation with args2 and mean. */
    double sum_sq_diff = 0;
    for (int i = 0; i < count; ++i)
    {
        double num = va_arg(args2, double);
        sum_sq_diff += (num - mean) * (num - mean);
    }
    va_end(args2);

    return sqrt(sum_sq_diff / count);
}

int main(void)
{
    printf("%f\n", sample_stddev(4, 25.0, 25.0, 25.0, 25.0));

	return 0;
}

 这个是va_copy的函数用法,

 

c语言的可变参数实例

标签:整数   必须   第一个   standard   存储   div   定义   argc   argv   

原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/11871451.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!