理解C中函数指针的typedef

时间:2009-10-19 21:55:46

标签: c function-pointers typedef

当我读到其他人的代码时,我总是有点难过,这些代码的typedef用于指向带参数的函数的指针。我记得在尝试理解用C语言编写的数值算法时,我花了一些时间来解决这个定义。那么,您是否可以分享您关于如何编写好的typedef指向函数(Do和Do)的提示和想法,为什么它们有用以及如何理解其他人的工作?谢谢!

7 个答案:

答案 0 :(得分:275)

答案 1 :(得分:71)

函数指针与任何其他指针一样,但它指向函数的地址而不是数据的地址(在堆或堆栈上)。像任何指针一样,它需要正确输入。函数由它们的返回值和它们接受的参数类型定义。因此,为了完整地描述函数,必须包含其返回值并接受每个参数的类型。 当你输入这样一个定义时,你会给它一个“友好名称”,这样就可以更容易地使用该定义创建和引用指针。

所以例如假设你有一个函数:

float doMultiplication (float num1, float num2 ) {
    return num1 * num2; }

然后是以下typedef:

typedef float(*pt2Func)(float, float);

可用于指向此doMulitplication函数。它只是定义一个指向函数的指针,该函数返回一个float并接受两个参数,每个参数都是float类型。此定义具有友好名称pt2Func。请注意,pt2Func可以指向ANY函数,该函数返回一个浮点数并接收2个浮点数。

所以你可以创建一个指向doMultiplication函数的指针,如下所示:

pt2Func *myFnPtr = &doMultiplication;

您可以使用此指针调用该函数,如下所示:

float result = (*myFnPtr)(2.0, 5.1);

这样可以很好地阅读:http://www.newty.de/fpt/index.html

答案 2 :(得分:30)

理解函数指针的typedef的一种非常简单的方法:

int add(int a, int b)
{
    return (a+b);
}

typedef int (*add_integer)(int, int); //declaration of function pointer

int main()
{
    add_integer addition = add; //typedef assigns a new variable i.e. "addition" to original function "add"
    int c = addition(11, 11);   //calling function via new variable
    printf("%d",c);
    return 0;
}

答案 3 :(得分:25)

cdecl是一个很好的工具,用于破译类似函数指针声明的奇怪语法。您也可以使用它来生成它们。

对于使复杂声明更容易解析以便将来维护(由您自己或其他人)的提示,我建议制作typedef小块并使用这些小块作为更大和更复杂表达式的构建块。例如:

typedef int (*FUNC_TYPE_1)(void);
typedef double (*FUNC_TYPE_2)(void);
typedef FUNC_TYPE_1 (*FUNC_TYPE_3)(FUNC_TYPE_2);

而不是:

typedef int (*(*FUNC_TYPE_3)(double (*)(void)))(void);

cdecl可以帮助您解决这些问题:

cdecl> explain int (*FUNC_TYPE_1)(void)
declare FUNC_TYPE_1 as pointer to function (void) returning int
cdecl> explain double (*FUNC_TYPE_2)(void)
declare FUNC_TYPE_2 as pointer to function (void) returning double
cdecl> declare FUNC_TYPE_3 as pointer to function (pointer to function (void) returning double) returning pointer to function (void) returning int
int (*(*FUNC_TYPE_3)(double (*)(void )))(void )

并且(实际上)正是我如何在上面产生那种疯狂的混乱。

答案 4 :(得分:12)

int add(int a, int b)
{
  return (a+b);
}
int minus(int a, int b)
{
  return (a-b);
}

typedef int (*math_func)(int, int); //declaration of function pointer

int main()
{
  math_func addition = add;  //typedef assigns a new variable i.e. "addition" to original function "add"
  math_func substract = minus; //typedef assigns a new variable i.e. "substract" to original function "minus"

  int c = addition(11, 11);   //calling function via new variable
  printf("%d\n",c);
  c = substract(11, 5);   //calling function via new variable
  printf("%d",c);
  return 0;
}

输出是:

22

6

请注意,同样的math_func定义器已用于声明该函数。

typedef的相同方法可用于extern结构。(在其他文件中使用sturuct。)

答案 5 :(得分:3)

这是我作为练习写的函数指针和函数指针数组的最简单的例子。

    typedef double (*pf)(double x);  /*this defines a type pf */

    double f1(double x) { return(x+x);}
    double f2(double x) { return(x*x);}

    pf pa[] = {f1, f2};


    main()
    {
        pf p;

        p = pa[0];
        printf("%f\n", p(3.0));
        p = pa[1];
        printf("%f\n", p(3.0));
    }

答案 6 :(得分:3)

使用typedef定义更复杂的类型,即函数指针

我将以C

中定义状态机为例
    typedef  int (*action_handler_t)(void *ctx, void *data);

现在我们已经定义了一个名为action_handler的类型,它接受两个指针并返回一个int

定义你的状态机

    typedef struct
    {
      state_t curr_state;   /* Enum for the Current state */
      event_t event;  /* Enum for the event */
      state_t next_state;   /* Enum for the next state */
      action_handler_t event_handler; /* Function-pointer to the action */

     }state_element;

指向动作的函数指针看起来像一个简单类型,而typedef主要用于此目的。

现在我的所有事件处理程序都应该遵循action_handler

定义的类型
    int handle_event_a(void *fsm_ctx, void *in_msg );

    int handle_event_b(void *fsm_ctx, void *in_msg );

参考文献:

Linden的专家C编程