可变参数列表:可以将它们收集在变量中吗?

Variable parameter lists: possibility to collect them in variable?

当 C 函数定义可变参数列表时

myfunc(int *i,...);

我可以调用它(根据它的正确用法),例如与

myfunc(&i,1,"hello",2,42);

myfunc(&i,"fish",13,33,"haktar",2,42);

但是有没有可能把这些参数数据收集到一个list里面,然后交给function呢?意味着是否有可用的变量类型允许这样的事情(伪代码):

arg_list list;

list.add("fish");
list.add(13);
list.add(33);
list.add("haktar");
myfunc(&i,list);

如果是:如何才能做到这一点?谢谢!

编辑:澄清一下:myfunc(int *i,...) 是给定的函数原型,无法修改,这意味着我必须处理“...”参数部分使用合适的 (va_arg-like?) 数据类型,我不能在那里使用简单的 array/chained list/other 自己的数据类型。

你的建议是你的函数需要填充某种结构,并将这个结构交给另一个函数。

希望对您有所帮助:

#include <stdio.h>

void GetParams(struct list *ptr,char *string1,int a,int b,char *string2);

void myfunc(int *i,struct list List);

struct list
{
char* string1;

int a;

int b;

char* string2;
};

int main(void)
{
int i;

list List;

GetParams(&List,"fish",13,33,"haktar");

myfunc(&i,List);


}

void GetParams(struct list *ptr,char *string1,int a,int b,char *string2)
{
ptr->string1 = string1;

ptr->a = a;

ptr->b = b;

ptr->string2 = string2;
}

void myfunc(int *i,struct list List)
{
*i = 1;
// ...
printf("i : %d\n",*i);

printf("%s\n",List.string1);
printf("%d\n",List.a);
printf("%d\n",List.b);
printf("%s\n",List.string2);
}

我假设你创建的列表有点像这样

typedef struct arg_list {
    void *data;
    struct arg_list *next;
}

您需要创建一个函数来将您的参数添加到列表中。

void list_add(arg_list **list, void *data)
{
    arg_list *elem;

    elem = malloc(sizeof(arg_list)); // check what malloc returns

    elem->data = data;
    elem->next = *list;
    *list = elem;
}

这是一个"sketch",别忘了分配你的数据! 这样,您的数据就会添加到列表的开头!

您可以添加如下内容:

list_add(&list, "Hello");
list_add(&list, 42);

编辑:忘了告诉你怎么用了。

您可以通过 list->datalist->next 使用它转到下一个元素。

这叫做链表。

您不能直接调用需要可变参数列表的函数。相反,您可以更改函数以接收例如包含允许参数类型联合的项目数组:

#include <stdio.h> 

enum arg_type { ARG_TYPE_INTEGER, ARG_TYPE_STRING };

struct arg {
    enum arg_type type;
    union {
        int integer;
        const char *string;
    };
};


static void myfunc(size_t length, struct arg list[length])
{
    for (size_t i = 0; i < length; i++) {
        printf("argument %zu: ", i);
        switch (list[i].type) {
            case ARG_TYPE_INTEGER: printf("integer: %d", list[i].integer); break;
            case ARG_TYPE_STRING: printf("string: %s", list[i].string); break;
        }
        puts("");
    }
}


int main()
{
    struct arg list[] = {
        { .type = ARG_TYPE_STRING, .string = "fish" },
        { .type = ARG_TYPE_INTEGER, .integer = 13 },
        { .type = ARG_TYPE_INTEGER, .integer = 33 },
        { .type = ARG_TYPE_STRING, .string = "haktar" }
    };

    myfunc(sizeof list / sizeof *list, list);
}

(请注意,这使用了 C11 语言功能;您可能需要在编译器中启用 C11 支持,例如,为 clang 或 gcc 使用 -std=c11 选项)

好的,正确答案似乎是:这是不可能的,因为所有这些用于可变参数的 va_* 东西都不是函数或数据类型,而是预处理器解析的宏。所以这一切似乎只用静态代码就可以实现,在运行时没有任何变化。