Reputation: 2121
foo();
(*foo)();
(&foo)();
What exactly is the difference between these function calls (assuming foo()
is defined somewhere)? and are there any situations where one might be used over another?
Also, why don't &foo()
and *foo()
work?
Upvotes: 17
Views: 2491
Reputation: 13852
Since this is tagged c++
, it's possible for a function to return a reference in that language, and such a function could be called as &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;
}
Upvotes: 0
Reputation: 123468
foo();
Calls a function named foo
.
(*foo)();
Calls a function through a pointer to a function named foo
; you typically see this when invoking a function that has been passed as a parameter to another function (also known as a callback):
/**
* 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);
}
The mapping in this example is kind of stupid, but it illustrates the concept. Just like you can have pointers to different data types, you can have pointers to different function types. Instead of executing a function named foo
, we're executing a function that's being pointed to by foo
.
Note that parentheses matter: the function call operator ()
has a higher precedence than unary *
, so the expression *foo()
would be interpreted as "call foo
and dereference the result", whereas (*foo)()
is interpreted as "dereference foo
and call the result".
(&foo)();
does the same thing as (*foo)();
, except that it's working through a reference instead of a pointer (C++ only). Again, parentheses matter; &foo()
is interepreted as "call foo
and take the address of the result", which isn't legal.
Upvotes: 0
Reputation: 145839
If foo
is a function designator, these are all equivalent in C:
foo();
(foo)();
(*foo)();
(***foo)();
(*&foo)();
Upvotes: 0
Reputation: 13196
There is no difference between the actual calls themselves (rather, they will all do the same thing depending on how foo()
is declared)
All function calls in C and C++ take place via a function-pointer expression which appears before the function call parentheses. Implicit address-of of non-pointer types takes place if necessary.
Here's an ideone demonstrating the behavior in C++.
The reason &foo()
and *foo()
don't work is that the function call operator ()
takes precedence over *
and &
. So they might work, depending on what you were doing with the return value. &foo()
would take the return value's address, and *foo()
would dereference it. Under some circumstances, either of these operations, or both, might be legal. Consider a function returning a reference-to-pointer type.
Part of this answer taken from R..'s comment.
Upvotes: 25
Reputation: 254461
You don't say exactly what foo
is, but I'll assume it's a function.
What exactly is there difference between these function calls?
Obviously, the first calls the function using the usual syntax.
The third takes the address of the function and attempts to call that; the language allows function pointers to be called as if they were the function they point to, so this is equivalent to foo()
.
The second tries to dereference the function. Dereferencing requires a pointer, and the language allows implicit conversion from a function to a pointer to that function, so this is equivalent to (*(&foo))()
, which in turn is equivalent to foo()
.
To summarise: all three do the same thing.
and are there any situations where one might be used over another?
Unless you like to decorate your code with unnecessary heiroglyphics, there's no reason to use anything other than the first form, for either functions or function pointers.
Also, why don't
&foo()
and*foo()
work?
The precedence rules mean that these are equivalent to &(foo())
and *(foo())
; i.e. they call the function and try to take the address of and dereference the result. The first form will "work" if the function has a return type; the second will "work" if it returns a pointer or (in C++) something with an overloaded unary operator*()
.
Upvotes: 10
Reputation: 4761
foo() calls function foo.
void foo() {return;}
foo();
(*foo)() dereferences a (function) pointer named foo, and calls it with zero arguments.
void bar() {return;}
int main(int argc, char** argv){
void(*foo)() = &bar;
(*foo)(); // works
(*bar)(); // also works
return 0;
}
(&foo)() takes the reference to a function foo, and calls it with zero arguments.
void bar() {return;}
int main(int argc, char** argv){
(&bar)();
return 0;
}
Hope that helped.
Upvotes: 0