所以我有两个函数可以做同样的事情但是在不同的类型变量上。
第一个函数在给定int arr[]
参数时填充整数数组。
当给定结构作为参数时,第二个函数也用整数填充链表。
链表参数的结构看起来像这样
typedef struct {node_t *head;int size;}
list_t;
现在我已经为这两个函数实现了一个函数指针表:
typedef struct{
char *name; //name of the function
void (*fill)(int arr[]); //fill up the array
} alg_t;
alg_t algs[] = {
{"func1",fill_up_arr},
{"func2",fill_up_linkedList}
};
请注意,在包含指针的struct中,fill函数指针
将int arr[]
作为参数。
我只想在该结构中使用一个函数的指针,有没有办法可以使用
类型转换,以便其他函数,如fill_up_linkedList
要求参数类型为list_t而不是int arr[]
?
//This is what I want my main to look like.
//I want func.fill to be called only once thus
//dynamically perform the operations for all functions inside the table of
//functions array
int arr = malloc(sizeof(int)algs.size);
for(int i = 0; i<algs.size;i++){
alg_t func = algs[i];
func.fill(arr);
}
似乎这个代码的问题是当循环尝试执行fill_up_LinkedList
函数时,因为它需要一个不同的参数。
在这种情况下如何使用类型转换?
由于
答案 0 :(得分:1)
C11 §6.3.2.3 Pointers ¶8(在一般主题§6.3 Conversions下)说:
指向一种类型的函数的指针可以转换为指向另一种函数的指针 打字再回来;结果应该等于原始指针。如果转换了 指针用于调用类型与引用类型不兼容的函数, 行为未定义。
这意味着您可以将任何和所有函数指针存储在公共函数指针类型中,例如typedef void (*GenericFunctionPointer)(void)
。但是,重要的是,在通过指针调用函数之前,从通用函数指针类型转换回正确的函数指针类型(并且您提供了正确的参数列表,并且您正确地处理了返回类型,虽然忽略了返回值,但如果有的话,总是一个选项。)
对于两个不同的函数指针类型,每个函数都有一个函数实例,支持它的基础结构可能比节省的更精细,如果有的话。另一方面,如果你有两个或更多不同的函数指针类型,并且大多数(如果不是所有)类型都有许多代表函数('many'表示'多于一个',如计算机工程师的计数:“零,一个,很多“),然后基础设施可以得到回报。其中一个问题是编组函数参数 - 如何使参数可访问,以便可以通过具有正确参数的指针调用该函数。
所以,这样做是复杂而冗长的。
我只想在结构中放一个函数。我的目标是找到一种方法,允许
fillArray
允许传递不同的参数。
我对使用不计数数组作为参数列表有很大的保留,如问题所示 - void (*fill)(int arr[])
。在我看来,它应该是void (*fill)(size_t n, int arr[n])
,使用可变长度数组表示法。如果您愿意,可以省略下标中的n
- void (*fill)(size_t n, int arr[])
- 甚至可以使用void (*fill)(int arr[], size_t n)
,这是参数的更经典的顺序。
抛开这个问题,如果你想让一个函数接受不同的参数,一种方法就是用void *
作为类型,但你必须知道这些问题 - 其中一个是类型安全。您还需要借鉴标准C函数qsort()
和bsearch()
中的想法。参数列表将包含指向数组开头的指针void *
,数组中每个元素的大小以及数组中元素的数量。您可能还需要比较器功能的类似物。
在单个被调用函数的内部,你可能最终会得到两个代码路径,所以尽管你通过指针调用一个函数,但你最终还是相当于实现了两个函数。您可以使用类似于qsort()
的接口,这样两个函数具有相同的接口和不同的主体,并且您在alg_t
数组中使用两个指针。
答案 1 :(得分:0)
使用联盟:
typedef struct {
char *name; //name of the function
union {
void(*fillArray)(int arr[]); //fill up the array
void(*fillList)(YourListType list); //fill up the list
};
} alg_t;
alg_t a;
a.fillArray(...);
a.fillList(...);
或者:
typedef struct {
char *name; //name of the function
union {
void(*fillArray)(int arr[]); //fill up the array
void(*fillList)(YourListType list); //fill up the list
} functions;
} alg_t;
alg_t a;
a.functions.fillArray(...);
a.functions.fillList(...);
答案 2 :(得分:0)
由于您只有2种类型,因此您只需使用枚举和宏
即可<div class="crumb">
<div class="arrowWrapper">
<span class="arrow"></span>
</div>
</div>
用你的函数名替换foo和bar
答案 3 :(得分:0)
如果您只遇到函数参数的问题而没有返回值,则有一个与不完整的类型定义相关的技巧。诀窍在于将指针类型声明中的参数列表留空,如:
typedef void (*callback_ptr)();
不同于:
typedef void (*callback_ptr)(void);
在第一种情况下,编译器不会检查传递给函数的参数,因为指针是指向未完全定义的函数类型的指针,而第二种显式表示该函数不需要参数,并且会给你一个如果您尝试与他们一起调用,则会出错。