C中函数指针语法的用途是什么?

时间:2014-10-09 22:09:46

标签: c pointers function-pointers

编辑:有人指出这个问题有点令人困惑。简短的版本是:“为什么有一个单独的指针变量(例如,fnPtr)指向一个函数(例如,fn)当函数名fn本身,没有参数,是已经指针?/编辑

我正在尝试理解某些内容,并且可以使用来自社区的有关函数指针的反馈。 (虽然这可能看起来像是关于这个主题的其他问题的重复,但实际上并非如此,至少不是我能找到的。)

我理解指向函数的指针的概念被用作另一个函数的参数作为回调...即告诉fn1在执行{{{}}期间以某种方式使用fn2 1}}。我不明白的是所有这些都使用了复杂的语法。如果fn1是已定义的函数,则调用fn将使用提供的参数执行该函数。但是,fn(...)本身使用的是函数的地址,即指向函数的指针。此外,fnfn&fn都是一样的。为什么要有专用的函数指针,以及为什么创建指向函数的新变量(即*fn)...函数名已经是它自己的指针了!

此代码每次编译和工作都相同。

fnPtr

最简单的语法是#include <stdlib.h> #include <stdio.h> int fn(int var) { //fn is a function which takes an int and returns an int return var; } int (*fnPtrAmp)(int) = &fn; int (*fnPtr)(int) = fn; int needsCallback(int variable, int callback(int)) { return callback(variable); } int needsCallbackPointer(int variable, int (*callbackPtr)(int)) { return callbackPtr(variable); } int needsCallbackPointerWithDereference(int variable, int (*callbackPtr)(int)) { return (*callbackPtr)(variable); } int main() { printf("%d\n", fn(4)); printf("%d\n", fnPtr(4)); printf("%d\n", (*fnPtr)(4)); printf("%d\n", needsCallback(4,fn)); printf("%d\n", needsCallbackPointer(4,fnPtr)); printf("%d\n", needsCallbackPointer(4,fn)); printf("%d\n", needsCallbackPointer(4,&fn)); printf("%d\n", needsCallbackPointerWithDereference(4,fnPtr)); printf("%d\n", needsCallbackPointerWithDereference(4,fn)); printf("%d\n", needsCallbackPointerWithDereference(4,&fn)); return 0; } ,但在任何地方都没有,它总是needsCallbackneedsCallbackPointer。为什么?使用fnPtrAmp,您甚至不必将额外变量定义为函数指针。正如我之前所说,函数名称是它自己的指针!

可以使用一些反馈......谢谢。

2 个答案:

答案 0 :(得分:3)

  1. 函数指针变量在以后的控制流修改函数指针时很有用(例如,选择不同的回调)。

    在处理运行时绑定时,函数指针变量也很有用,在编译时你不知道函数,而是在运行时分配函数指针,例如使用dlsym。这通常用于可扩展API(例如,OpenGL是此方案的流行用户)和插件的上下文中。

  2. “最简单的语法是needsCallback,但是在任何地方都没有,它总是需要CallbackPointer和fnPtrAmp。为什么?”:在函数的参数中声明与变量或typedef声明的方式一致看起来像。

  3. 您提出的另一个问题是为什么*fnPtr有效,为什么是括号

    嗯,括号是必需的,因为函数调用操作符()的优先级高于解除引用操作符*,因此首先调用该函数,然后取消返回值。 (*fnPtr)()可以解决这个问题。

  4. someFunction &someFunction 是等效的,因为函数不是C中的一等公民(函数不是可以操作的普通对象,如例如int,但函数指针是。因此,函数名称始终固有地转换为指向该名称引用的函数的函数指针。请注意,您可以多次将&应用于函数指针,产生指向函数指针的指针,指向指向函数指针的指针等。因此,它在*的意义上不起作用,你可以在函数指针上随意使用。

  5. *fnPtr 有效,因为函数指针上使用的*运算符实际上会产生完全相同的指针。与4)相同的基本原理 - 语言中没有函数对象。因此,您无法从函数指针返回函数名称,这是不可能的。

  6. 我不知道为什么这些运算符分别是为函数名和指针定义的。也许是历史原因?为了与其他指针类型保持一致?

    我怀疑稍后会引入无操作符语法以节省输入,因为您无法在rvalue和lvalue上下文中有意义地使用函数名。既然没有人可以用函数指针做任何事情(除了传递它。你当然可以改变它,比如fnPtr++;但是它会在哪里得到你?),添加隐含它是非常有意义的转换使fnPtr()成为可能,以便再次保存输入。

    (最后两段是我的纯粹推测。)

答案 1 :(得分:0)

C中函数指针语法的目的是双重

1)混淆程序员

2)允许编译器语法检查函数指针的调用者是否使用与函数本身相同的参数。

第二个是导致大多数混淆的原因,因为如果你有一个返回指针的函数指针,那么derefence(*)的绑定不能按预期工作,你必须添加额外的括号。

-A