【问题标题】:What is the purpose of Function Pointer syntax in C?C中函数指针语法的目的是什么?
【发布时间】:2014-12-04 23:49:47
【问题描述】:

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

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

我理解一个函数的指针被用作另一个函数的参数作为回调的概念......即告诉fn1 在执行fn1 期间以某种方式使用fn2。我不明白的是所有这些都使用了复杂的语法。如果fn 是已定义函数,则调用fn(...) 将使用提供的参数执行该函数。但是,单独使用的fn是函数的地址,也就是指向函数的指针。此外,fn&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;
}

最简单的语法是needsCallback,但这不是在任何地方都可以做到的,它总是needsCallbackPointerfnPtrAmp。为什么?使用needsCallback,您甚至不必定义额外的变量作为函数指针。前面说了,函数名就是它自己的指针!

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

【问题讨论】:

  • 您询问了五个不同的问题,并在您自己的帖子中回答了其中一些问题。您的实际问题是什么?
  • 似乎有两个问题:(1)为什么有函数指针?(2)为什么函数名上允许&amp;,而函数指针上允许*。您在自己的帖子中使用回调示例回答 (1),并且 (2) 得到回答 here
  • 问题不在于为什么有函数指针本身,而是为什么有一个单独的指针变量(例如,fnPtr),它指向一个函数(例如,fn),而函数名fn 本身,不带参数,已经是指针了?
  • 如果你有多个函数可供选择,你只需要创建一个单独的函数指针variable,但是直到运行时才做出选择。否则,如果你知道你总是会传递一个指向同一个特定函数的指针,使用那个特定的函数名。
  • @austin1howard 你写了这段代码,所以我很困惑你为什么问“为什么有这个代码”。这就像说“当我以后可以写5 时,int x = 5; 有什么意义”

标签: c pointers function-pointers


【解决方案1】:
  1. 函数指针变量在随后的控制流修改函数指针(例如选择不同的回调)时很有用。

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

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

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

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

  4. someFunction&amp;someFunction 是等价的,因为函数不是 C 中的一等公民(函数不是可以操作的普通对象,例如 int) ,但函数指针是。因此,函数名称始终且固有地转换为指向该名称引用的函数的函数指针。请注意,您可以将&amp; 多次应用于函数指针,产生指向函数指针的指针、指向函数指针的指针等。因此,它在某种意义上不像* 那样表现,您可以将其用作经常在函数指针上随心所欲。

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

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

我怀疑后来引入了无运算符语法以节省键入,因为您不能在右值或左值上下文中有意义地使用函数名称。由于函数指针也无能为力(除了传递它。您当然可以更改它,例如 fnPtr++; 但这对您有什么帮助?),添加隐式转换非常有意义fnPtr() 可能,再次节省输入。

(最后两段纯属个人猜测。)

【讨论】:

  • 感谢 dom0,这更有意义。我了解取消引用和地址运算符(* 和 &);这基本上就是我问这个问题的原因。如果**fn、*fn、fn、&fn、~~&&fn~~之间没有区别,那为什么还要使用它们呢。
  • 我编辑了我的答案,&amp;fn&amp;&amp;fn 之间存在 区别。
  • 是的,抱歉,我明白了……我是在不假思索地打字。
  • 我不确定。也许是历史原因或与其他指针类型的一致性。它也可能有助于阅读源代码,但这充其量是值得怀疑的。
  • 哦,你在那一堆代码后面隐藏了第五个问题。也为那个添加了答案(我的答案中的第二个)。
【解决方案2】:

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

1) 迷惑程序员

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

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

-A

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 2012-12-16
    • 1970-01-01
    相关资源
    最近更新 更多