22

我对如何将指针传递给指针函数有点困惑。我有一个函数,它需要一个指向我理解没有问题的函数的指针(ExecBlock)。但是我得到了另一个函数原型ExecBlock2(如果有人可以解释优先级以及取消引用指针函数会做什么。那不只是传递函数本身吗?在这种情况下做什么(void *)

int ExecBlock (void (*f) (void), int isSet)
{
    return ExecBlock2( HOW TO PASS HERE? , NULL, isSet);
}

int ExecBlock2(void *(*f)(void *), void *arg, int isSet)
{
    ... more code
}
4

2 回答 2

46
void (*f) (void)

表示指向函数的指针,没有返回 void 的参数。

void *(*f)(void *)

表示指向函数的指针,采用 void 指针并返回 void 指针。

由于类型不同,编译器将不允许您将一个传递给另一个而不进行强制转换。(请注意,强制转换在这里并不是真正的正确答案,正如@detly 指出的那样,会导致未定义的行为。)

至于取消引用指向函数的指针,您不必在函数指针之前显式放置“*”来调用它。例如,您可以通过调用函数指针 f

f();

函数指针示例

假设你有一个函数f,你想将它传递给一个名为takes_a_function. takes_a_function可能会有类似的类型

void takes_a_function(void (*f)(void *data), void *data);

注意 有两个参数takes_a_function,一个函数指针和一个指向某些数据的 void 指针。另请注意,该函数f恰好将 void 指针作为参数。这个想法是您可以将数据传递给takes_a_function,它会将其传递给f。例如,takes_a_function可以定义为

void takes_a_function(void (*f)(void *), void *data) {
  f(data);
}

现在,让我们编写一个函数来传递给takes_a_function. 我们的函数将只打印一个传递给它的 int。

void prints_an_int(void *data) {
  // The idiom for converting a void pointer to another kind
  // of pointer.  NO NEED TO CAST.  Note this behavior is only
  // defined if the pointer data really does point to an int.
  int *i = data;
  printf("%d", *i);
}

int i = 0;
takes_a_function(prints_an_int, &i);

关于这个例子的几个关键点:

  • prints_an_int与预期的函数指针具有相同的类型takes_a_function。不需要投。
  • 无需使用&运算符来创建对函数的引用。这就是为什么我们可以直接传递prints_an_inttakes_a_function。但我们也可以说takes_a_function(&prints_an_int, &i), 也是一样的。
  • void*基本上意味着“指向未知类型的指针”。要真正用它做任何事情,您必须将一个类型的变量分配void*给另一个您期望其类型的指针变量。仅当您实际传入正确的指针类型时,才能保证有效!在这个例子中,我们可以赋值data给一个int*,因为 data 确实指向一个 int。如果你想要更多的数据而不仅仅是一个整数,一个常见的模式是创建你自己的结构类型,其中包括你想要的所有字段,然后传递它。
  • 作为一种特殊情况,编译器在将 void 指针分配给其他指针时不要求您进行强制转换,反之亦然。但同样,如果您最终将 void 指针转换回正确的类型,您只会获得定义的行为。
于 2013-10-17T03:42:40.080 回答
1

例如你有一个函数

void * abc(void *)
{
//... 
}

int ExecBlock (void (*f) (void), int isSet)
    {
        return ExecBlock2( abc , NULL, isSet); //use name of the function which have void * as parameter type list and return type  void *   
        }

int ExecBlock2(void *(*f)(void *), void *arg, int isSet)
{
    ... more code
}  

函数指针

于 2013-10-17T03:42:30.193 回答