当C函数定义像
这样的变量参数列表时myfunc(int *i,...);
我可以打电话给它(根据它的正确用法),例如与
myfunc(&i,1,"hello",2,42);
或
myfunc(&i,"fish",13,33,"haktar",2,42);
但是还有可能在列表中收集这些参数数据,然后将其交给函数吗?意味着有一个可用的变量类型允许这样的东西(伪代码):
arg_list list;
list.add("fish");
list.add(13);
list.add(33);
list.add("haktar");
myfunc(&i,list);
如果是的话:怎么能完全做到这一点?谢谢!
编辑:为了澄清这一点:myfunc(int * i,...)是一个给定的函数原型,无法修改,意味着我必须使用合适的处理“...”参数部分(va_arg-like?)数据类型,我不能使用简单的数组/链表/其他自己的数据类型。
答案 0 :(得分:2)
您无法直接调用期望变量参数列表的函数。相反,您可以更改函数以接收例如包含允许的参数类型的联合的项目数组:
#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
选项)
答案 1 :(得分:0)
你的建议是你的函数需要填充某种结构,并将这个结构移交给另一个函数。
我希望这会有所帮助:
#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);
}
答案 2 :(得分:0)
我假设您创建的列表有点像这样
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
使用它来转到下一个元素。
这称为链表。
答案 3 :(得分:0)
好的,正确答案似乎是:它是不可能的,因为用于变量参数的所有这些va_ * thingies都不是函数或数据类型,而是由预处理器解析的宏。所以这一切似乎只能用静态代码实现,在运行时没有任何改变。