C语言 C 中具有不同参数的不同函数的函数指针

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16770690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:28:41  来源:igfitidea点击:

Function pointer to different functions with different arguments in C

cfunction-pointers

提问by fahad

I have two functions with variable number and types of arguments

我有两个具有可变数量和参数类型的函数

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 }

I want to use a pointer to a function to the functions I defined above based on a some condition getting true e.g.

我想使用一个指向函数的指针,该函数指向我上面定义的基于某个条件为真的函数,例如

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);

My question is, for this scenario, Can I at all define a function pointer? If yes, how?
My understanding is that the prototype of function pointer should be the same for all those functions it CAN be pointed to.

我的问题是,对于这种情况,我可以定义一个函数指针吗?如果是,如何?
我的理解是,函数指针的原型对于它可以指向的所有函数应该是相同的。

typedef double (*pfunction)(int, int);

In my case they are not the same. Is there any other way to do this?

就我而言,它们不一样。有没有其他方法可以做到这一点?

Language

I am developing in C and I am using gcc 4.4.3 compiler/linker

我正在用 C 进行开发,我正在使用 gcc 4.4.3 编译器/链接器

采纳答案by Oliver Charlesworth

My question is, for this scenario, Can I at all define a function pointer?

我的问题是,对于这种情况,我可以定义一个函数指针吗?

No. (Other than by dirty typecasting.)

不。(除了肮脏的类型转换。)

Is there any other way to do this?

有没有其他方法可以做到这一点?

Your best bet is to create a wrapper function for one of your existing functions. For example:

最好的办法是为现有函数之一创建一个包装函数。例如:

double my_func_one_wrapper(double x, double p[], double c) {
    return my_func_one(x, p[0], p[1], c);
}

That way, you have two functions with the same signature, and therefore the same function-pointer type.

这样,您就有两个具有相同签名的函数,因此具有相同的函数指针类型。

回答by unwind

The cleanest way to do it is to use a union:

最干净的方法是使用联合:

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;

Then you can initialize an instance of the union, and include information to the swap_functionfunction to say which field is valid:

然后你可以初始化联合的一个实例,并在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);

This assumes that swap_functioncan know based on condition_1being falsethat it should assume condition_2. Note that the union is passed by value; it's only a function pointer in size after all so that's not more expensive than passing a pointer to it.

这假定swap_function可以知道根据condition_1false,它应该承担condition_2。注意联合是按值传递的;毕竟它只是一个大小的函数指针,所以这并不比将指针传递给它更昂贵。

回答by bash.d

Your understanding is true.
The signature of your function-pointer must match the corresponding function(s).

你的理解是对的。
函数指针的签名必须与相应的函数匹配。

Consider learncpp.com:

考虑learncpp.com

Just like it is possible to declare a non-constant pointer to a variable, it's also possible to >declare a non-constant pointer to a function. The syntax for doing so is one of the ugliest things >you will ever see:

就像可以声明指向变量的非常量指针一样,也可以>声明指向函数的非常量指针。这样做的语法是您将看到的最丑陋的事情之一:

// pFoo is a pointer to a function that takes no arguments and returns an integer 
int (*pFoo) (); 

The parenthesis around *pFoo are necessary for precedence reasons, as int *pFoo()would be interpreted as a function named pFoothat takes no parameters and returns a pointer to an integer.

In the above snippet, pFoois a pointer to a function that has no parameters and returns an integer. pFoocan “point” to any function that matches this signature.

...

Note that the signature (parameters and return value) of the function pointer must match the signature of the function.

出于优先考虑,*pFoo 周围的括号是必需的,因为 int*pFoo()将被解释为一个pFoo不带参数并返回指向整数的指针的函数。

在上面的片段中,pFoo是一个指向没有参数并返回整数的函数的指针。pFoo可以“指向”与此签名匹配的任何函数。

...

请注意,函数指针的签名(参数和返回值)必须与函数的签名匹配。

回答by Jens Gustedt

What you want is possible, but a bit dirty. Function pointers can be cast to one another without losing information. The important thing is that you'd always have to calla function through such a pointer only with a signature that corresponds to its definition. So ifyou cast back before calling the function(s) and call with the correct arguments, all should be fine.

你想要的是可能的,但有点脏。函数指针可以相互转换而不会丢失信息。重要的是,您总是必须通过这样的指针调用函数,并且只能使用与其定义相对应的签名。因此,如果您在调用函数之前回滚并使用正确的参数调用,一切都应该没问题。

回答by Katsu

An old topic but I am facing same issue and finally came with this idea.

一个老话题,但我面临同样的问题,最后提出了这个想法。

If you want the same prototype for each functions you can wrap the parameters in structure like this :

如果你想为每个函数使用相同的原型,你可以将参数包装在这样的结构中:

 typedef struct {
     double a,
            b,
            c; 
 }chunk1_t;

  typedef struct {
     double p[];
     double c; 
 }chunk2_t;

Then your function pointer becomes:

然后你的函数指针变成:

 double (*pfunc) (double x, void *args);

which leads to something like this :

这导致了这样的事情:

 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);
 }

Using function pointer stored in structure:

使用存储在结构中的函数指针:

 #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);

回答by Sujith Shiva

A sample of Typecasting approach for using a same function pointer for different functions of different prototypes. <>

对不同原型的不同函数使用相同函数指针的类型转换方法示例。<>

#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;
}