可变参数列表:可以将它们收集在变量中吗?
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->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);
}
(请注意,这使用了 C11 语言功能;您可能需要在编译器中启用 C11 支持,例如,为 clang 或 gcc 使用 -std=c11
选项)
好的,正确答案似乎是:这是不可能的,因为所有这些用于可变参数的 va_* 东西都不是函数或数据类型,而是预处理器解析的宏。所以这一切似乎只用静态代码就可以实现,在运行时没有任何变化。
当 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->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);
}
(请注意,这使用了 C11 语言功能;您可能需要在编译器中启用 C11 支持,例如,为 clang 或 gcc 使用 -std=c11
选项)
好的,正确答案似乎是:这是不可能的,因为所有这些用于可变参数的 va_* 东西都不是函数或数据类型,而是预处理器解析的宏。所以这一切似乎只用静态代码就可以实现,在运行时没有任何变化。