C 为什么函数指针有用?

C 为什么函数指针有用?,c,function,pointers,C,Function,Pointers,所以,我查看了函数指针,在我看到的示例中,特别是在这个答案中。它们似乎有些多余 例如,如果我有以下代码: int addInt(int n, int m) { return n+m; } int (*functionPtr)(int,int); functionPtr = &addInt; int sum = (*functionPtr)(2, 3); // sum == 5 在这里,创建函数指针似乎没有任何意义,这样做不是更容易吗 int sum = addInt(2, 3)

所以,我查看了函数指针,在我看到的示例中,特别是在这个答案中。它们似乎有些多余

例如,如果我有以下代码:

int addInt(int n, int m) {
    return n+m;
}
int (*functionPtr)(int,int);
functionPtr = &addInt;
int sum = (*functionPtr)(2, 3); // sum == 5
在这里,创建函数指针似乎没有任何意义,这样做不是更容易吗

int sum = addInt(2, 3); // sum == 5

如果是的话,那么你为什么需要使用它们,那么它们有什么用途呢?为什么您需要将函数指针传递给其他函数呢?如果您正在编写一个用户在其中输入函数的库呢?这样可以在任何类型上工作,但用户必须编写并提供比较函数

它的签名是

void qsort (void* base, size_t num, size_t size,
        int (*compar)(const void*,const void*));

它们减少了模块之间的依赖关系。有时,库必须查询调用代码,以确定这些对象是否相等?它们是按一定的顺序排列的吗?。但是,如果不使库a依赖于调用代码,而库b不依赖于非泛型代码,则无法硬编码对适当函数的调用


函数指针提供丢失的信息片段,同时保持库模块与可能使用它的任何代码无关。

当API需要回调回应用程序时,它们是必不可少的。

另一个用途是实现事件发射器或信号处理程序:函数。

简单的示例指针似乎同样无用。当你开始做更复杂的事情时,它会有所帮助。例如:

// Elsewhere in the code, there's a sum_without_safety function that blindly
// adds the two numbers, and a sum_with_safety function that validates the 
// numbers before adding them.

int (*sum_function)(int, int);
if(needs_safety) {
    sum_function = sum_with_safety;
}
else {
    sum_function = sum_without_safety;
}
int sum = sum_function(2, 3);
   typedef struct
    {
       void (*send)(int length, unsigned char* data);
    } connection_t;

    void connection_send(connection_t* self, int length, unsigned char* data)
    {
       if(self->send != NULL) self->send(length, data);
    }

    void serial_send(int length, unsigned char* data)
    {
     // send
    }

    void tcp_send(int length, unsgined char* data)
    {
    // send
    }


void create_serial_connection(connection_t* connection)
{
   connection->send = serial_send;
}
或:

或:


最后一个例子基本上是C++如何实现虚拟成员函数。将methods结构替换为哈希表,您就有了Objective-C的方法分派。与变量指针一样,函数指针允许您以有价值的方式抽象事物,从而使代码更加紧凑和灵活。然而,从最简单的例子来看,这种能力并不明显。

它们是C语言中最有用的东西之一!它们允许你制作更多的模块化软件

回调

例如

这意味着在您的代码中,您可以使用常规串行例程……然后您可能会有两种东西使用串行、modbus和terminal

serial_port_data_received(modbus_handle_data);
serial_port_data_received(terminal_handle_data);
他们可以实现回调函数并做适当的事情

它们允许面向对象的C代码。这是一种创建接口的简单方法,然后每个具体类型可能实现不同的功能。为此,通常您将有一个具有函数指针的结构,然后是实现每个函数指针的函数,以及一个使用正确函数设置函数指针的创建函数

   typedef struct
    {
       void (*send)(int length, unsigned char* data);
    } connection_t;

    void connection_send(connection_t* self, int length, unsigned char* data)
    {
       if(self->send != NULL) self->send(length, data);
    }

    void serial_send(int length, unsigned char* data)
    {
     // send
    }

    void tcp_send(int length, unsgined char* data)
    {
    // send
    }


void create_serial_connection(connection_t* connection)
{
   connection->send = serial_send;
}

然后,其他代码可以使用连接,而不必关心它是通过串行、tcp还是您能想到的任何其他方式。

听起来像是您自己回答了问题的一部分,将函数指针传递给其他函数搜索高阶函数还是一级函数。@DavidConrad,我会的,谢谢!正如其他人所指出的,它们非常有用。我个人不把它们用于函数重载,这在C语言中是很俗气的,但在比较函数的情况下,它们是不可或缺的,比如你可以传递给qsort的函数,以及它们为特定信号指定信号处理程序所需的存在性。因此,通过编写比较函数,并将其传递给qsort,用户可以决定要排序的元素类型?但是为什么函数指针的类型是int?@Link,函数返回的类型是int,表示对象之间的关系。按照惯例,零表示相等,正整数表示第二个对象大于第一个对象,依此类推。@StoryTeller,好吧,但这并不一定意味着传递的函数必须是int?@Link,传递的函数必须返回一个int。为了返回所说的int,可以随意重新解释void poiners。回调的具体含义是什么?您能解释一下代码中发生了什么吗?我有点困惑。这可能有点不清楚,因为*和&对于函数指针是可选的。如果你写sum_时没有括号,那么这不是调用,而是操作的get地址。类似地,只需在末尾加上括号就可以调用函数指针,无需先取消引用。好吧,这更有意义,但第一个示例的最后一点是,为什么/它对sum function=sum有安全性或无安全性做了什么?想象一下,例如,你正在对美式足球或橄榄球分数求和。部分分数有效;其他人则不然。你写一个没有安全性的快速求和,它只是盲目地将数字相加,而写一个带有安全性的慢速求和,它检查数字是否有效。然后有一个命令行开关来选择是否需要安全检查。你可以只做ifneeds\u safety{sum=sum\u with\u safety2,3;}或者{sum=sum\u without\u safety2,3;},但是如果你多次求和,检查一下needs\u safety并设置一个函数指针可能会更干净。好吧,但是我想我可能对函数点有点不清楚 那好吧。您的声明如下:int*sum\u functionint,int;但是,它不应该被称为sum函数,而不是有安全性或无安全性的sum函数吗?
serial_port_data_received(modbus_handle_data);
serial_port_data_received(terminal_handle_data);
   typedef struct
    {
       void (*send)(int length, unsigned char* data);
    } connection_t;

    void connection_send(connection_t* self, int length, unsigned char* data)
    {
       if(self->send != NULL) self->send(length, data);
    }

    void serial_send(int length, unsigned char* data)
    {
     // send
    }

    void tcp_send(int length, unsgined char* data)
    {
    // send
    }


void create_serial_connection(connection_t* connection)
{
   connection->send = serial_send;
}