不带星号的函数指针参数

Posted

技术标签:

【中文标题】不带星号的函数指针参数【英文标题】:Function pointer parameter without asterisk 【发布时间】:2019-11-30 06:51:36 【问题描述】:

我见过这个函数的定义,它接收一个函数指针作为参数:

double fin_diff(double f(double), double x, double h  = 0.01) 
  return (f(x+h)-f(x)) / h;

我习惯用星号看到这个定义,即:

double fin_diff(double (*f)(double), double x, double h  = 0.01);

你知道为什么第一个定义也有效吗?

【问题讨论】:

函数和函数指针在用作函数的参数时具有相同的含义。 虽然您需要了解函数指针等,但在 C++ 中,如果可以避免的话,您真的不应该自己使用它们。如果您打算直接调用该函数,如示例所示,请改用模板。否则使用std::function。使用模板或std::function 通过允许您传递具有正确签名的任何类型的可调用对象(如 lambda、仿函数对象、实际函数指针等)来增加灵活性。 语言cc++ 是两种不同的语言。请选择一个并删除另一个tag,因为答案因语言而异 【参考方案1】:

标准说这两个函数是等价的,因为函数参数被调整为指向函数参数的指针:

16.1 可重载声明 [over.load] (3.3) 只有一个是函数类型而另一个是指向相同函数类型的指针的参数声明是等价的。即函数类型调整为指向函数类型的指针(11.3.5)。

在 C 中相同:

6.7.5.3 函数声明符(包括原型) 8 将参数声明为“函数返回类型”应调整为“指向的指针” 函数返回类型'',如 6.3.2.1。

【讨论】:

哪个标准? C 还是 C++? @GiacomoAlzetta 我还添加了 C 标准的引用。第一个显然来自 C++,因为 C 没有重载【参考方案2】:

指向函数的指针是特殊的。给定一个函数void f();,你可以这样做

void (*fptr)() = f;
void (*fptr)() = &f;
void (*fptr)() = &&f;
void (*fptr)() = &&&f;

无限。

同样,当你通过函数指针调用函数时,你可以这样做

fptr();
(*fptr)();
(**fptr)();
(***fptr)();

无限。

一切都崩溃了。

【讨论】:

这样做的动机是什么?并不是说这种无限链接是不可能的(考虑一个指针,其引用值包含它自己的地址),但我不明白为什么所有函数都应该这样。 @Alexander -- 它在时间的迷雾中消失了。 @Alexander -- 说真的,这来自 C,据我所知,一直如此。我不知道它的原因。 根据 James McNellis 的说法是 C++'s best feature。【参考方案3】:

如果函数参数被指定为函数声明,那么编译器本身会隐式地将参数调整为函数指针。

这类似于将函数名作为其他函数的参数传递,例如

fin_diff( func_name, 10.0 );

编译器再次将函数指示符隐式转换为指向函数的指针。

【讨论】:

以上是关于不带星号的函数指针参数的主要内容,如果未能解决你的问题,请参考以下文章

C语言指针学习总结

JavaScript 中怎么不带括号的调用函数

参数中的星号和与号

数据结构的函数名前加星号*和它的返回值有啥关系?

带/不带指针的函数原型使用区别

指针*和取地址&函数输入使用