Take the 2-minute tour ×

While working my way through The C++ Programming Language (TCPL), I found myself implementing the calculator program in Chapter 6. In debugging my code, I noticed that I had typed get_token; instead of get_token();. With the error, the program still compiled, but it did nothing. Easy fix.

This got me to thinking about what a function name really means. I was trying to figure out when you would ever just use the function's name without the () operator. Then it came to me, function pointer definitions!

Unfortunately, as I played around with what I once remembered about function pointers, I found that I could not satisfactorily understand what was going on.

Here is what I was toying with:

void foo() {
    cout << "Foo to you too!\n";

int main() {
    void (*p1_foo)() = foo;
    void (*p2_foo)() = *foo;
    void (*p3_foo)() = &foo;
    void (*p4_foo)() = *&foo;
    void (*p5_foo)() = &*foo;
    void (*p6_foo)() = **foo;
    void (*p7_foo)() = **********************foo;


The crazy part (to me anyway!) is that all seven pointers worked and successfully called the function, printing Foo to you too!... Indeed!!

So what is really going on here?

share|improve this question
add comment

1 Answer

up vote 105 down vote accepted

There are a few pieces to this that allow all of these combinations of operators to work the same way.

The fundamental reason why all of these work is that a function (like foo) is implicitly convertible to a pointer to the function. This is why void (*p1_foo)() = foo; works: foo is implicitly converted into a pointer to itself and that pointer is assigned to p1_foo.

The unary &, when applied to a function, yields a pointer to the function, just like it yields the address of an object when it is applied to an object. For pointers to ordinary functions, it is always redundant because of the implicit function-to-function-pointer conversion. In any case, this is why void (*p3_foo)() = &foo; works.

The unary *, when applied to a function pointer, yields the pointed-to function, just like it yields the pointed-to object when it is applied to an ordinary pointer to an object.

These rules can be combined. Consider your second to last example, **foo:

  • First, foo is implicitly converted to a pointer to itself and the first * is applied to that function pointer, yielding the function foo again.
  • Then, the result is again implicitly converted to a pointer to itself and the second * is applied, again yielding the function foo.
  • It is then implicitly converted to a function pointer again and assigned to the variable.

You can add as many *s as you like, the result is always the same. The more *s, the merrier.

We can also consider your fifth example, &*foo:

  • First, foo is implicitly converted to a pointer to itself; the unary * is applied, yielding foo again.
  • Then, the & is applied to foo, yielding a pointer to foo, which is assigned to the variable.

The & can only be applied to a function though, not to a function that has been converted to a function pointer (unless, of course, the function pointer is a variable, in which case the result is a pointer-to-a-pointer-to-a-function; for example, you could add to your list void (**pp_foo)() = &p7_foo;).

This is why &&foo doesn't work: &foo is not a function; it is a function pointer that is an rvalue. However, &*&*&*&*&*&*foo would work, as would &******&foo, because in both of those expressions the & is always applied to a function and not to an rvalue function pointer.

Note also that you do not need to use the unary * to make the call via the function pointer; both (*p1_foo)(); and (p1_foo)(); have the same result, again because of the function-to-function-pointer conversion.

share|improve this answer
@Jimmy: Those aren't references to function pointers, they are just function pointers. &foo takes the address of foo, which results in a function pointer pointing at foo, as one would expect. –  Dennis Zickefoose Aug 1 '11 at 0:59
I've updated the answer with a more correct (and far lengthier) explanation. It suffices to say that function pointers in C and C++ are bizarre. –  James McNellis Aug 1 '11 at 1:01
You can't chain & operators for objects either: given int p;, &p yields a pointer to p and is an rvalue expression; the & operator requires an lvalue expression. –  James McNellis Aug 1 '11 at 1:15
I disagree. The more *'s, the less merry. –  Seth Carnegie Aug 1 '11 at 1:28
Please do not edit the syntax of my examples. I have picked the examples very specifically to demonstrate features of the language. –  James McNellis Mar 4 '12 at 5:58
show 6 more comments

Your Answer


