将数组的所有元素传递给具有可变参数的函数(...)

时间:2014-10-09 09:40:39

标签: c parameters optional-parameters

我需要将可变数量的参数传递给允许可变数量参数的c函数。

function a(int n , ...) {...} //*n* number of parameters

int b[XXX]; //XXX is more or less run-time dynamic.
//Filsignals.https://github.com/libpd/libpd/blob/master/pure-data/src/d_ugen.cl b with things.
a(n, b[0], b[1] ... b[XXX])

如何在不命名b的每个元素的情况下编写此内容?

一件事:我无法更改a()的实施,并使用va_list来访问" ..."。 因此,我不能将a(n, b)作为" b"只会作为一个参数处理,但它包含更多。

更多细节:a()实际上是puredata dsp_add()函数(在d_ugen.c中定义),它使用传递的指针来设置传入和传出。

一个选项

我发现我可以使用dsp_addv()来避免此问题,{{3}}是可变参数dsp_add()函数的数组版本。

然而,这并没有回答我的问题......

2 个答案:

答案 0 :(得分:2)

您已经找到了问题的答案。我认为使用函数的数组变体是要走的路。 (对dsp_addv函数的评论很有说服力。)

  

然而,这并没有回答我的问题......

根据可变参数函数的性质,您可以编写一个调用可变参数函数的包装函数。这不适用于所有情况,但适用于一些常见情况。 (Variadic函数本身在使用时受到限制。在某个地方,我读过一个声称它们只存在于实现printf的声明。)

迭代

对每个可变参数进行了一些操作:例如,它被打印,或者被添加到列表中。在这种情况下,您只需为每个参数调用函数:

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

void varg_print(const char *str, ...)
{
    va_list va;

    va_start(va, str);
    while (str) {
        puts(str);
        str = va_arg(va, const char *);
    }
    va_end(va);
}

void arr_print(const char **str)
{    
    while (*str) varg_print(*str++, NULL);
}

int main()
{
    const char *fruit[]) = {"apple", "pear", "banana", NULL};
    arr_print(fruit);

    return 0;
}

减少

所有参数都减少为单个值,例如它们的总和或它们的最大值。在这里,你可以处理子阵列,直到你得到你想要的。下面的示例一次将一个数组转发到一个求和函数,最多四个元素,并用结果覆盖数组的下部区域,直到只剩下一个值。

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

double varg_sum(int n, ...)
{
    double s = 0.0;
    va_list va;

    va_start(va, n);
    while (n--) s += va_arg(va, double);
    va_end(va);

    return s;
}

double arr_sum(int n, double *x)
{
    double r[n];

    if (n <= 0) return 0.0;

    memcpy(r, x, n * sizeof(*x));

    while (n > 1) {
        double *p = r;
        int m = 0;

        while (n) {
            switch (n) {
            case 1:     r[m++] = varg_sum(1, p[0]);
                        n -= 1;
                        p += 1;
                        break;

            case 2:     r[m++] = varg_sum(2, p[0], p[1]);
                        n -= 2;
                        p += 2;
                        break;

            case 3:     r[m++] = varg_sum(3, p[0], p[1], p[2]);
                        n -= 3;
                        p += 3;
                        break;

            default:    r[m++] = varg_sum(4, p[0], p[1], p[2], p[3]);
                        n -= 4;
                        p += 4;
                        break;
            }
        }

        n = m;   
    }

    return r[0];
}

int main()
{
    double x[100];
    int i;

    for (i = 0; i < 100; i++) x[i] = i + 1.0;
    printf("%g\n", arr_sum(100, x));   

    return 0;
}

代码生成数组的副本,以便不破坏原始数组。您可以增加块大小以便更有效地处理更大的数组,但无论如何,可变参数函数不适用于长可变参数列表,所以四个似乎没问题。

答案 1 :(得分:0)

a()是可以修改的内容还是其他内容的api的一部分?

如果您可以更改它,而不是使用可变参数函数,我将该函数定义为:

function a(int n, int* params)
{
    /*...*/
}

然后将数组传递给它。

如果它不是一个选项,我会查看linked question并将其实现为包装函数,这样您就可以将数组传递给它,使代码保持简单可能的。