我有两个具有可变数量和参数类型的函数
double my_func_one(double x, double a, double b, double c) { return x + a + b + c }
double my_func_two(double x, double p[], double c) { return x + p[0] + p[1] + c }
我想根据一些条件得到实际使用指向上面定义的函数的函数的指针,例如。
if (true == condition_1)
pfunc = my_func_one;
else if (true == condition_2)
pfunc = my_func_two;
// The function that will use the function I passed to it
swap_function(a, b, pfunc);
我的问题是,对于这种情况,我能否定义一个函数指针?如果是,怎么样?
我的理解是函数指针的原型应该与它可以指向的所有函数相同。
typedef double (*pfunction)(int, int);
就我而言,他们并不相同。还有其他办法吗?
我正在用C开发,我正在使用gcc 4.4.3编译器/链接器
答案 0 :(得分:19)
最干净的方法是使用联合:
typedef union {
double (*func_one)(double x, double a, double b, double c);
double (*func_two)(double x, double p[], double c);
} func_one_two;
然后你可以初始化union的一个实例,并在swap_function
函数中包含信息,说明哪个字段有效:
func_one_two func;
if (condition_1)
func.func_one = my_func_one;
else if (condition_2)
func.func_two = my_func_two;
// The function that will use the function I passed to it
swap_function(a, b, func, condition_1);
这假设swap_function
可以根据condition_1
false
知道它应该假设condition_2
。请注意,union按值传递;它毕竟只是一个大小的函数指针,所以它并不比传递指针更昂贵。
答案 1 :(得分:10)
我的问题是,对于这种情况,我能否定义一个函数指针?
没有。 (除了肮脏的类型转换。)
还有其他办法吗?
最好的办法是为现有的一个功能创建一个包装函数。例如:
double my_func_one_wrapper(double x, double p[], double c) {
return my_func_one(x, p[0], p[1], c);
}
这样,你有两个具有相同签名的函数,因此函数指针类型相同。
答案 2 :(得分:1)
你的理解是真的 函数指针的签名必须与相应的函数匹配。
考虑learncpp.com:
就像可以声明一个指向变量的非常量指针一样,也可以> gt;声明一个指向函数的非常量指针。这样做的语法是>你将看到的最丑陋的事情之一:
// pFoo is a pointer to a function that takes no arguments and returns an integer
int (*pFoo) ();
出于优先原因,* pFoo周围的括号是必需的,因为int
*pFoo()
将被解释为名为pFoo
的函数,它不接受任何参数并返回指向整数的指针。在上面的代码片段中,
pFoo
是一个指向没有参数并返回整数的函数的指针。pFoo
可以“指向”与此签名匹配的任何函数。...
请注意,函数指针的签名(参数和返回值)必须与函数的签名匹配。
答案 3 :(得分:1)
你想要什么是可能的,但有点脏。函数指针可以相互转换而不会丢失信息。重要的是,你总是必须通过这样的指针调用一个函数,只有一个与其定义相对应的签名。所以 if 如果你在调用函数之前强制转换并使用正确的参数调用,那么一切都应该没问题。
答案 4 :(得分:1)
一个古老的话题,但我面临着同样的问题,最后想到了这个主意。
如果每个功能都需要相同的原型,则可以将参数包装在这样的结构中:
typedef struct {
double a,
b,
c;
}chunk1_t;
typedef struct {
double p[];
double c;
}chunk2_t;
然后您的函数指针将变为:
double (*pfunc) (double x, void *args);
这会导致类似这样的结果:
pfunc cb;
double swap_function(double x, pfunc cb, void *args);
double my_func_one(double x, void *args) {
chunk1_t *chunk = (chunk1_t*) args;
return x + chunk->a + chunk->b + chunk->c;
}
double my_func_two(double x, void *args) {
chunk2_t *chunk = (chunk2_t*) args;
return x + chunk->p[0] + chunk->p[1] + chunk->c ;
}
int main(){
// declare a, b,...
double a = 1.0f;
//...
// cast for safety
chunk1_t myChunk1 = {(double)a, (double)b, (double)c};
// don't if you like risk
chunk2_t myChunk2 = {p, c};
swap_function(x, cb, &myChunk1);
swap_function(x, cb, &myChunk2);
}
使用存储在结构中的函数指针:
#define FUNC_ONE_METHOD 1
#define FUNC_TWO_METHOD 2
typedef struct chunk{
double a, b, c;
double p[];
int method;
double (*pfunc) (double x, struct chunk *self);
}chunk_t;
double swap_function(double x, chunk_t *ch){
switch (ch->method)
{
case FUNC_TWO_METHOD:
ch->pfunc = my_func_two;
break;
case FUNC_ONE_METHOD:
ch->pfunc = my_func_one;
break;
default:
return -1; // or throw error
return ch->pfunc(x, ch);
}
chunk c = {.a= 1, .b=3, .c=1, .method=1};
swap_function(x, &c);
答案 5 :(得分:-2)
针对不同原型的不同功能使用相同函数指针的类型转换方法示例。 <>
#include <stdio.h>
typedef void (*myFuncPtrType) (void);
typedef int (*myFunc2PtrType)(int, int);
typedef int * (*myFunc3PtrType)(int *);
static void myFunc_1 (void);
static int myFunc_2 (int, int);
static int* myFunc_3 (int *);
const myFuncPtrType myFuncPtrA[] = {
(myFuncPtrType)myFunc_1,
(myFuncPtrType)myFunc_2,
(myFuncPtrType)myFunc_3
};
static void myFunc_1 (void)
{
printf("I am in myFunc_1 \n");
}
static int myFunc_2 (int a, int b)
{
printf("I am in myFunc_2\n");
return (a+b);
}
static int* myFunc_3 (int *ptr)
{
printf("I am in myFunc_3\n");
*ptr = ((*ptr) * 2);
return (ptr+1);
}
int main(void) {
// your code goes here
int A[2],C;
int* PTR = A;
(*(myFuncPtrA[0]))();
A[0]=5;
A[1]=6;
C = ((myFunc2PtrType)(*(myFuncPtrA[1])))(A[0],A[1]);
printf("Value of C: %d \n", C);
printf("Value of PTR before myFunc_3: %p \n", PTR);
printf("Value of *PTR before myFunc_3: %d \n", *PTR);
PTR = ((myFunc3PtrType)(*(myFuncPtrA[2])))(&A);
//Lets look how PTR has changed after the myFunc_3 call
printf("Value of PTR after myFunc_3: %p \n", PTR);
printf("Value of *PTR after myFunc_3: %d \n", *PTR);
return 0;
}