bqui56
bqui56

Reputation: 2121

What is the difference between calling functions in the following way?

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

Answers (6)

Matt K
Matt K

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

John Bode
John Bode

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

ouah
ouah

Reputation: 145839

If foo is a function designator, these are all equivalent in C:

foo();
(foo)();
(*foo)();
(***foo)();
(*&foo)();

Upvotes: 0

Wug
Wug

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

Mike Seymour
Mike Seymour

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

Moritz
Moritz

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

Related Questions