foo();
(*foo)();
(&foo)();
这些函数调用之间到底有什么区别(假设foo()
在某处定义)?有没有可能在另一种情况下使用一个?
另外,为什么不&foo()
工作*foo()
?
实际调用本身没有区别(相反,它们都会根据foo()
声明的方式做同样的事情)
C 和 C++ 中的所有函数调用都是通过出现在函数调用括号之前的函数指针表达式进行的。如有必要,会发生非指针类型的隐式寻址。
&foo()
and*foo()
不起作用的原因是函数调用运算符()
优先于*
and &
。因此它们可能会起作用,具体取决于您对返回值所做的事情。 &foo()
将获取返回值的地址,并*foo()
取消引用它。在某些情况下,这些操作中的任何一个或两者都可能是合法的。考虑一个返回引用指针类型的函数。
此答案的一部分取自 R.. 的评论。
你没有确切地说是什么foo
,但我会假设它是一个函数。
这些函数调用之间到底有什么区别?
显然,第一个使用通常的语法调用函数。
第三个获取函数的地址并尝试调用它;该语言允许调用函数指针,就好像它们是它们指向的函数一样,所以这相当于foo()
.
第二个尝试取消引用该函数。取消引用需要一个指针,并且该语言允许从函数隐式转换为指向该函数的指针,因此 this 等价于(*(&foo))()
,而后者又等价于foo()
.
总结一下:这三个都做同样的事情。
有没有可能在另一种情况下使用一个?
除非你喜欢用不必要的象形文字来装饰你的代码,否则没有理由对函数或函数指针使用第一种形式以外的任何东西。
另外,为什么不
&foo()
工作*foo()
?
优先规则意味着这些等价于&(foo())
and *(foo())
; 即他们调用函数并尝试获取结果的地址并取消引用。如果函数具有返回类型,则第一种形式将“起作用”;如果它返回一个指针或(在 C++ 中)带有重载的 unary 的东西,第二个将“工作” operator*()
。
foo() 调用函数 foo。
void foo() {return;}
foo();
(*foo)() 取消引用名为 foo 的(函数)指针,并用零参数调用它。
void bar() {return;}
int main(int argc, char** argv){
void(*foo)() = &bar;
(*foo)(); // works
(*bar)(); // also works
return 0;
}
(&foo)() 获取对函数 foo 的引用,并使用零参数调用它。
void bar() {return;}
int main(int argc, char** argv){
(&bar)();
return 0;
}
希望有帮助。
Iffoo
是一个函数指示符,这些在 C 中都是等价的:
foo();
(foo)();
(*foo)();
(***foo)();
(*&foo)();
foo();
调用名为 的函数foo
。
(*foo)();
通过指向名为;的函数的指针调用函数 foo
在调用已作为参数传递给另一个函数(也称为回调)的函数时,您通常会看到这一点:
/**
* Execute the function pointed to by "foo" for each element
* in the array.
*/
void map(int *arr, size_t arrsize, void (*foo)(int))
{
size_t i;
for (i = 0; i < arrsize; i++)
(*foo)(arr[i]); // can also be called as foo(arr[i]);
}
void bar(int i)
{
printf("i = %d\n", i);
}
int main(void)
{
int arr[] = {1, 2, 3, 4, 5};
/**
* Call the function "bar" for each member
* of "arr".
*/
map(arr, sizeof arr / sizeof *arr, bar);
}
这个例子中的映射有点愚蠢,但它说明了这个概念。就像您可以拥有指向不同数据类型的指针一样,您也可以拥有指向不同函数类型的指针。我们不是执行一个名为 的函数,而是foo
执行一个由 指向的函数foo
。
请注意,括号很重要:函数调用运算符()
的优先级高于 unary *
,因此表达式*foo()
将被解释为“调用foo
并取消引用结果”,而(*foo)()
被解释为“取消引用foo
并调用结果”。
(&foo)();
与 做同样的事情(*foo)();
,只是它通过引用而不是指针工作(仅限 C++)。同样,括号很重要。&foo()
被解释为“调用foo
并获取结果的地址”,这是不合法的。
由于这是标记c++
的,因此函数可以返回该语言的引用,并且可以将这样的函数称为&foo()
:
#include <iostream>
using std::cout;
using std::endl;
int & foo() {
static int f = 5;
return f;
}
int main() {
cout << foo() << endl;
*(&foo()) = 7;
cout << foo() << endl;
return 0;
}