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

2024-03-03

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

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

我理解指向函数的指针被用作另一个函数的参数作为回调的概念......即告诉fn1 to use fn2在执行过程中以某种方式fn1。我不明白的是所有这些都使用了复杂的语法。如果fn是一个定义的函数,然后调用fn(...)将使用提供的参数执行该函数。然而,fn单独使用的是函数的地址,即指向函数的指针。此外,fn, &fn, and *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但这并没有在任何地方完成,它总是needsCallbackPointer and fnPtrAmp。为什么?和needsCallback您甚至不必定义额外的变量作为函数指针。正如我之前所说,函数名称是它自己的指针!

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


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

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

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

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

    好吧,括号是必需的,因为函数调用运算符()具有比解引用运算符更高的优先级*,因此首先调用该函数,然后取消引用返回值。(*fnPtr)()围绕这个工作。

  4. someFunction and &someFunction是等价的,因为函数不是 C 中的一等公民(函数不是可以操作的普通对象,就像int,例如),但函数指针是。因此,函数名称总是本质上转换为指向该名称引用的函数的函数指针。请注意,您可以申请&多次指向函数指针,产生指向函数指针的指针、指向函数指针的指针等。因此,它的行为并不像*确实如此,您可以在函数指针上随意使用它。

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C 中函数指针语法的用途是什么? 的相关文章

  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • 赋值运算符和复制构造函数有什么区别?

    我不明白C 中赋值构造函数和复制构造函数之间的区别 是这样的 class A public A cout lt lt A A lt lt endl The copy constructor A a b The assignment cons
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 为什么基类必须有一个带有 0 个参数的构造函数?

    这不会编译 namespace Constructor0Args class Base public Base int x class Derived Base class Program static void Main string a
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • C++11 函数局部静态 const 对象的线程安全初始化

    这个问题已在 C 98 上下文中提出 并在该上下文中得到回答 但没有明确说明有关 C 11 的内容 const some type create const thingy lock my lock some mutex static con
  • 如何用 kevent() 替换 select() 以获得更高的性能?

    来自Kqueue 维基百科页面 http en wikipedia org wiki Kqueue Kqueue 在内核和用户空间之间提供高效的输入和输出事件管道 因此 可以修改事件过滤器以及接收待处理事件 同时每次主事件循环迭代仅使用对
  • 单元测试失败,异常代码为 c0000005

    我正在尝试使用本机单元测试项目在 Visual Studios 2012 中创建单元测试 这是我的测试 TEST METHOD CalculationsRoundTests int result Calculations Round 1 0
  • 通过不同 DLL 或 EXE 中的指针或引用访问 STL 对象时发生访问冲突

    我在使用旧版 VC6 时遇到以下问题 我只是无法切换到现代编译器 因为我正在处理遗留代码库 http support microsoft com kb 172396 http support microsoft com kb 172396
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • std::bind 重载解析

    下面的代码工作正常 include
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • 32位PPC rlwinm指令

    我在理解上有点困难rlwinmPPC 汇编指令 旋转左字立即然后与掩码 我正在尝试反转函数的这一部分 rlwinm r3 r3 0 28 28 我已经知道什么了r3 is r3在本例中是一个 4 字节整数 但我不确定这条指令到底是什么rlw
  • 运行代码首先迁移更新数据库时出错

    我在迁移到数据库时遇到问题 并且似乎找不到我遇到的错误的答案 System MissingMethodException Method not found System Data Entity Migrations Builders Tab
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS

随机推荐