一、可变长参数介绍

某些情况下为了完成一些功能,需要用到可变长参数的函数,例如我们最常用的printf和scanf函数:

scanf("%d %d", &a, &b);
printf("%d %d\n", a, b);

它们首先都是一个字符串打头,后面再跟上不定数量的参数,为我们的输出形式提供了多样性。

对于像这样的不定长参数的函数来说,它的声明形式为:

int func(int a, int b, ...);

...表示不定长度的参数,和函数形参的默认值一样,...也只能放在函数的最后,否则函数无法判断出哪些才是不定参数。

二、变参使用

变参函数内部是通过栈来实现的,对于每一个参数来说,在调用时它们都会从右到左依次被压入栈中,而栈的性质是先进后出,所以在使用时会从左到右提取。

C语言中定义了一种类型va_list来提取这些参数,va_list类型的定义如下:

// stdarg.h
typedef va_list char*

提取需要用到的API函数为va_startva_arg,其用法如下:

void f(const char *arg, ...) {
    va_list args;
    //初始化args指向强制参数arg的下一个参数,即第一个不定参数的地址
    va_start(args, arg);
    //获取当前参数内容并将args指向下一个参数,type表示当前的元素类型
    va_arg(args, type);
    // ... 操作

    va_end(args); //释放args
}

三、使用示例

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

/*
 * 求和
 * @param argc  参数个数
 * @param ...   可变参数列表
 * @return      所有参数的和
 */
int sum(int argc, ...) {
    int sum = 0, tmp;
    // 初始化参数
    va_list argv;
    va_start(argv, argc); 

    for (int i = 0; i < argc; i++) {
        // 循环获取每一个参数
        tmp = va_arg(argv, int);
        printf("%d\n", tmp);
        sum += tmp;
    }

    // 销毁参数
    va_end(argv);
    return sum;
}

int main() {
    printf("sum = %d\n", sum(3, 10, 20, 30));
    printf("sum = %d\n", sum(4, 40, 39, 38, 37));

    return 0;
}

运行结果:

$ ./debug/app
10
20
30
sum = 60
40
39
38
37
sum = 154
最后修改:2018 年 05 月 07 日
如果觉得我的文章对你有用,请随意赞赏