C 变量参数列表:是否可以在变量中收集它们?

C 变量参数列表:是否可以在变量中收集它们?,c,variadic-functions,C,Variadic Functions,当C函数定义变量参数列表时,如 myfunc(int *i,...); 我可以(根据它的正确用法)称它为 myfunc(&i,1,"hello",2,42); 或 但是,是否也可以在列表中收集这些参数数据,然后将其移交给函数?意味着是否有一种变量类型允许这样的操作(伪代码): 如果是:具体如何做到这一点?谢谢 编辑:为了澄清这一点:myfunc(int*i,…)是一个不能修改的给定函数原型,这意味着我必须使用合适的(va_arg-like?)数据类型来处理“…”参数部分,我不能在那里

当C函数定义变量参数列表时,如

myfunc(int *i,...);
我可以(根据它的正确用法)称它为

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

但是,是否也可以在列表中收集这些参数数据,然后将其移交给函数?意味着是否有一种变量类型允许这样的操作(伪代码):

如果是:具体如何做到这一点?谢谢


编辑:为了澄清这一点:myfunc(int*i,…)是一个不能修改的给定函数原型,这意味着我必须使用合适的(va_arg-like?)数据类型来处理“…”参数部分,我不能在那里使用简单的数组/链表/其他自己的数据类型。

您建议的是,您的函数需要填充某种结构,这个结构可以交给另一个函数

我希望这有助于:

#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);
}
#包括
void GetParams(结构列表*ptr,字符*string1,int a,int b,字符*string2);
void myfunc(int*i,结构列表);
结构列表
{
字符*string1;
INTA;
int b;
字符*string2;
};
内部主(空)
{
int i;
名单;
GetParams(&List,“fish”,13,33,“haktar”);
myfunc(&i,列表);
}
void GetParams(结构列表*ptr,字符*string1,int a,int b,字符*string2)
{
ptr->string1=string1;
ptr->a=a;
ptr->b=b;
ptr->string2=string2;
}
void myfunc(int*i,结构列表)
{
*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;
}
这是一个“草图”,别忘了分配数据! 这样,您的数据将添加到列表的开头

您可以添加如下内容:

list_add(&list, "Hello");
list_add(&list, 42);
编辑:我忘了告诉你怎么用它了

您可以通过
list->data
list->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);
}
#包括
枚举arg_类型{arg_类型_整数,arg_类型_字符串};
结构参数{
枚举参数类型;
联合{
整数;
常量字符*字符串;
};
};
静态void myfunc(大小\长度,结构参数列表[长度])
{
对于(大小i=0;i

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

好的,正确答案似乎是:不可能,因为所有用于变量参数的变量都不是函数或数据类型,而是由预处理器解析的宏。因此,这一切似乎只适用于静态代码,运行时不会发生任何变化。

为什么不使用数组??Akansha:当int和char[]可以混合使用时,数组的数据类型是什么?您的第一个函数,
myfunc(int*i,…)
不能明智地与C变量参数一起使用。函数如何知道哪个参数是字符串,哪个参数是数字。(
printf
scanf
知道,因为格式字符串中有格式说明符。)您的列表方法看起来更有希望,但您必须创建一个变量数据类型,它可以存储数字和字符串,并且始终知道它是哪种类型。第一个参数是否定义了后面的参数数量?下面的参数类型是:string,int,int,string,int,int,…?machine_1:谢谢你的建议,但这是我想要避免的。在ANSI-C中已经存在一些类似va_arg的数据类型,它们能够以某种方式处理不同的数据,我更愿意使用它们。但问题是,如果真的可以从外部使用它们或仅将其用作函数参数,那么stdarg.h中的va_arg类型只能用于传递已经是函数调用参数的参数列表。把它想象成一个指针,指向调用函数时存储参数的堆栈上的某个位置。这主意不错,但我不能将此列表交给我帖子中描述的“…”类型的参数。你确定要使用变量列表吗?因为这是同一件事。您仍然可以将创建的列表交给这样的函数
func(&i,list)
,并将列表与itI中的所有数据一起使用。我必须使用变量参数列表,因为此处需要使用的API希望这是ok。那么您应该知道,这段代码的问题与原始参数列表的问题相同:您需要知道哪段数据属于哪种类型。(在这里,这可以通过向节点结构添加一个类型字段来解决,就像dpi发布的变量类型一样。)请参阅我上面帖子中的编辑-我无法更改功能,我没有访问权限
list_add(&list, "Hello");
list_add(&list, 42);
#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);
}