我想实现一个参数数量可变的函数。此函数允许我使用可选参数列表调用另一个函数。该函数的目的是根据某些条件调用任何函数(取决于调用的函数,如果前两个参数相等,我们调用该函数(。我的问题是,可以调用的函数没有相同数量的参数,因此,我不知道每次我有不同的函数时如何传递参数
例如,如果我有这个:
void func(int value_to_compare, int compared_value, int arg_number, char *arg_types, char *function_name, ...)
我可以这样称呼它:
char arg1;
int arg2, arg3;
int condition1;
func(condition1, 1, 1, "c", func1, arg1);
func(condition1, 0, 2, "ci", func2, arg1, arg2);
func(arg2, 0 , 3, "cii", func3, arg1, arg2, arg3);
调用的函数如下所示:
func1(char);
func2(char, int);
func3(char, int, int);
我尝试解释更多,例如:
struct element_list {
char *element_type;
char *element_name;
}
在我的例子中,结构有大量元素,条件必须作为参数传递给函数,条件值取决于上下文,所以我必须能够在任何上下文中调用'func',我只是给出条件和值,然后一个函数将被调用与相应的参数, 所以它会像
func(element_list.element_type, "CHAR", func1, "s", element_list.element_name);
除此之外,我还有大量的函数和大量的条件,所以我需要一些尽可能通用的东西。
无论你在做什么,现在你都在围绕类型系统工作。在 C 中没有类型安全的方法可以执行您想要的操作。
牢记这一点:
一种可能的解决方案是使所有函数具有相同的类型:typedef void my_func_type(void*)
并让每个函数自行"解密"参数。
另一个解决方案是重新考虑您的设计 - 这是我真诚推荐给您的解决方案。但首先你需要多说一点你想在这里实现的目标......一个好的起点是展示您打算如何使用此类功能。很有可能你最终根本不需要这个......
续,#1
据我了解,你会想写这样的func
,以至于这段代码
char arg1;
int arg2, arg3;
int condition1;
func(condition1, 1, 1, "c", func1, arg1);
func(condition1, 0, 2, "ci", func2, arg1, arg2);
func(arg2, 0 , 3, "cii", func3, arg1, arg2, arg3);
行为如下:
if (condition1 == 1) func1(arg1);
if (condition1 == 0) func2(arg1, arg2);
if (arg2 == 0) func3(arg1, arg2, arg3);
坦率 地 说。。。最好的方法是这样写。:-)
既然你问这个问题,你可能想要更复杂的东西。情况是这样的:您希望在代码的控制流上构建一些抽象。这就是函数式编程风格派上用场的地方......事实上,在C++中,事情会很简单(嗯,不是真的微不足道,但可以以类型安全和可移植的方式完成,使用一些模板神奇的奇怪功能,名称中带有bind
(。
我们谈论的是 C 而不是 C++,没有模板,没有函子......所以事情可能比这更复杂。但首先要做的是 - 是什么阻止您使用带有 if 的简单解决方案?回答这个问题是一个好的开始。
你有两个选择。 首选方法是通过具有输入类型和为该类型输入定义的各种值的struct
传递输入。 然后,您只需将struct
传递给函数(通过引用/指针(。
第二个选项是格式化参数,以便您可以使用 va_start
、 va_arg
和 va_end
来读取它们。 要使用它,您需要知道下一个 arg 的类型,因此您需要将其作为输入传递。 您还需要提前知道何时到达最后一个参数,因此同样,您需要将其作为输入传递。 这与printf
的工作方式相同,以及为什么您需要将格式字符串传递给printf
。
好的,这是我的做法
void func(int value_type, void *value_to_compare, void *compared_value, char *arg_types, void (*function_name)(), ...)
我根据类型在value_type上切换,在value_to_compare上进行转换,compared_value,将这些值存储在两个不同的联合中,然后比较它们,如果值相等,我调用函数function_name。关于要调用的函数,我根据arg_types进行强制转换,然后我做了一些非常愚蠢的事情,这是一个开关,例如:
switch(strlen(arg_types)) {
case 0:
function_name();
break;
case 1:
function_name(args[0]);
break;
case 2:
function_name(args[0], args[1]);
break;
...
}
其中参数是
void* args[MAX_NUMBER_ARGS];
我采用数组参数的每个元素,并根据arg_types进行强制转换,但我找不到更好的解决方案......