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

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

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

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

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

 #include  #include  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; } 

最简单的语法是needsCallback但是在任何地方都没有,它总是需要needsCallbackPointerfnPtrAmp 。 为什么? 使用needsCallback您甚至不必将额外变量定义为函数指针。 正如我之前所说,函数名称是它自己的指针!

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

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

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

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

  3. 你问的另一个问题是为什么*fnPtr工作,为什么括号

    好吧,括号是必需的,因为函数调用operator ()的优先级高于取消引用运算符* ,因此首先调用该函数,然后取消返回值。 (*fnPtr)()解决这个问题。

  4. someFunction&someFunction是等价的,因为函数不是C中的一等公民(函数不是可以被操纵的普通对象,例如int ),但是函数指针是。 因此,函数名称始终固有地转换为指向该名称引用的函数的函数指针。 请注意,您可以多次对函数指针应用,产生指向函数指针的指针,指向指向函数指针的指针等。因此它的行为与* do不同,您可以根据需要随意使用在函数指针上。

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

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

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

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

C中函数指针语法的目的有两个

1)混淆程序员

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

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

-一个