当我阅读其他人的代码时,我总是有点困惑,这些代码为带有参数的函数指针提供了typedefs。我记得,当我试图理解不久前用C语言编写的数值算法时,我花了一段时间才得到这样的定义。那么,关于如何为函数指针编写良好的typedef (Do's和Do's),以及它们为什么有用以及如何理解其他人的工作,您能分享一下您的技巧和想法吗?谢谢!


当前回答

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 )

这(事实上)正是我如何产生上面那个疯狂的混乱。

其他回答

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 )

这(事实上)正是我如何产生上面那个疯狂的混乱。

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 struct。(在其他文件中使用struct)

宏呢?我已经看到,使用类型定义,我不能将一些东西强制转换为函数指针。所以我为它做了这个小宏,它能够做我到目前为止需要的所有事情(不知道它不能用于什么-我认为它基本上是一个类型定义,但有一个可选参数,使它在类型转换中可用):

#define funcptr_t(sym_name) void (*sym_name)(void)

// Declare a function pointer-returning function, and declare a function pointer variable.
funcptr_t (randomFunction(funcptr_t (func_ptr_variable)));
// Cast a variable to a function pointer
(funcptr_t()) some_variable;

PS:我做这个通用用途,不确定它是否可以修改为特定的功能使用。

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

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

使用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语言编程专家