Passing all elements of an array to a function with variable parameters (…)

假如想象 提交于 2019-12-24 05:19:26

问题


I need to pass a variable number of parameters to a c-function that allows a variable number of parameters.

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])

How to write this without naming each single element of b?

One thing: I cannot change the implementation of a() and it uses the va_list to access "...". Thus, I cannot pass a(n, b) as "b" would only be handled as one parameter only, but it contains more.

Just more details: a() is actually the puredata dsp_add() function (defined in d_ugen.c) that is uses the passed pointers to set up incoming and outgoing.

One option

I just found that I can avoid this problem by using dsp_addv(), which is an array version of the variadic dsp_add() function.

However, this does not answer my question...


回答1:


You have already found an answer to your problem. I think using the array variant of the function is the way to go. (The comment on the dsp_addv function is telling.)

However, this does not answer my question...

Depending on the nature of the variadic function, you can write a wrapper function that calls the variadic function. This will not work in all cases, but for some frequent cases. (Variadic functions themselves are rather restricted in their use. Somewhere, I've read a claim that they exist only to implement printf.)

Iteration

Something is done to each variadic argument: It is printed, for example, or it is added to a list. In that case you can just call the function for each argument:

#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;
}

Reduction

All arguments are reduced to a single value, for example their sum or their max values. Here you can treat sub-arrays until you get what you want. The example below forwards an array to a summation function at most four elements at a time and overwrites the lower regions of the array with the result until there is only a single value left.

#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;
}

The code makes a copy of the array so that the original array isn't destroyed. You can increase the chunk size in order to treat bigger arrays more effectively, but variadic functions aren't designed for long variadic lists anyway, so four seems okay.




回答2:


Is a() something that can be modified or part of the api of something else?

If you can change it, instead of using a variadic function, I'd define the function as:

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

and just pass the array into it.

If it isn't an option, I'd look into the linked question and implement it into a wrapper function, so you can just pass your array to that, keeping your code as simple as possible.



来源:https://stackoverflow.com/questions/26275163/passing-all-elements-of-an-array-to-a-function-with-variable-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!