6

Possible Duplicate:
How does dereferencing of a function pointer happen?

If we have

void f() {
    printf("called");
}

Then the following code will result in output of "calledcalled":

f();
(*f)();

I don't really understand how this works…what is the difference between *f and f? And why would you call a function using the latter syntax?

Community
  • 1
  • 1
Aaron Yodaiken
  • 19,163
  • 32
  • 103
  • 184
  • 1
    This needs to be two questions, one about C, one about C++, because they have subtly different rules (although the same behavior in the end). – Ben Voigt Apr 30 '11 at 20:49

3 Answers3

6

The first one is somewhat of a syntactic sugar for the second one. The second one makes it obvious that you're making the call through a pointer, and it's used mainly with function pointers rather than regular functions, to make the distinction more obvious.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • So is the second one implicitly taking the pointer to `f`, and then calling the function via that? – Matti Virkkunen Apr 30 '11 at 20:13
  • 2
    @Matti: No, the second one is *dereferencing* the pointer and calling the function, which is what the first one *implicitly* does. (The `*` symbol has several meanings -- it can be both the dereferencing *operator* and a pointer *declaration*, aside from multiplication. Don't get them confused.) – user541686 Apr 30 '11 at 20:14
  • f is an address. (*f)() is a function call to that address. – Scott C Wilson Apr 30 '11 at 20:14
  • Actually, yes: the second one is implicitly interpreted as `(*&f)();`, but this is only due to C heritage. In C++ you 'should' take the address of explicitly. – Jan Apr 30 '11 at 20:17
  • @Jan: I believe the *first* one is implicitly interpreted like that, not the second one... `f` *is* the function pointer, not a value whose *address* is the pointer. – user541686 Apr 30 '11 at 20:19
  • @Mehrdad: I'm pretty sure a plain call to a function and a call via a function pointer are (at least without optimization) compiled differently, so by default `f` is just the function `f` and not a pointer to it. What I meant by "implicitly taking the pointer" referred to the lack of `&`. – Matti Virkkunen Apr 30 '11 at 20:20
  • @Matti: I'm confused -- what is the distinction between "the function `f`" and "a pointer to the function `f`"? AFAIK the function *is* the pointer and nothing else... `&f` just makes it obvious that you mean the address of `f`, but otherwise, it's just like how the name of an array is the same as the address of its first element. – user541686 Apr 30 '11 at 20:22
  • @Mehrdad: Technically, `f` is a function, and `&f` is the "address" of a function; they have different types. But typically, one degrades into another, just like for arrays turning into pointers (which are *not* the same thing, by the way...). – Oliver Charlesworth Apr 30 '11 at 20:23
  • @Oli: I still don't see the distinction -- in what way is a function `f` different from its address `&f`? AFAIK they're the same semantically (both are l-values, both have the same data type, etc.) – user541686 Apr 30 '11 at 20:24
  • 2
    Guys, `f` and `*f` are the same thing because the indirection operator, when applied to a function, returns a function designator which is the same as the function itself. This is discussed at length [here](http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-function-pointer-happen). – Frédéric Hamidi Apr 30 '11 at 20:24
  • @Frederic: Nice catch, voting to close as duplicate... – user541686 Apr 30 '11 at 20:26
  • @Mehrdad: A plain call to a function and a call via a pointer to it get compiled into different kinds of instructions on a lot of platforms. That's what makes a function and a pointer to it different. In the trivial case of something like `(*&f)()` the whole pointer thing gets optimized away and becomes a plain call in the end, though. – Matti Virkkunen Apr 30 '11 at 20:30
  • @Matti: I wasn't asking how the *call* is different, I was saying how the *value* of `f` and `&f` are not different. Yes, there's an indirect call and there's a direct call, but that's only because of a compiler optimization, not a C semantics difference. – user541686 Apr 30 '11 at 20:32
  • @Mehrdad: But the semantics ARE different. There is no function pointer involved in the line `f();`. – Ben Voigt Apr 30 '11 at 20:35
  • @Ben: `f` *is* the (r-value) pointer... I don't see how that's any different. – user541686 Apr 30 '11 at 20:39
  • I couldn't just let this go and I went and took a look at [the standard](http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf) (section 6.5.2.2) (or at least the first of many C standards I could find) - and indeed, function calls are defined as a postfix operator where the function to call is an expression that returns a function pointer. There's even a footnote that mentions that "Most often, this is the result of converting an identifier that is a function designator." So, all function calls are defined via pointers. Guess you learn something new every day... – Matti Virkkunen Apr 30 '11 at 20:45
  • @Mehrdad, @Matti: Latest C++ standard language: "For an ordinary function call, the postfix expression shall be either an lvalue that refers to a function (in which case the function-to-pointer standard conversion (4.3) is suppressed on the postfix expression), or it shall have pointer to function type." Just another reason that the only questions that should be tagged both `c` and `c++` are the ones "How can I make this work in both C and C++" or related "Explain this difference between C and C++". – Ben Voigt Apr 30 '11 at 20:48
  • @Matti: That's what I always thought. :) @Ben: Interesting, so it's different in C++? Did *not* know that... – user541686 Apr 30 '11 at 21:30
6

There are two ways to call a function in C++:

By name:

f();

Through a function pointer:

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

Now, using the address-of operator on a function name (&f) obviously creates a function pointer. But the function name can implicitly convert to a function pointer when certain conditions are met. So the above code could be written as:

typedef void (*fptr_t)();
fptr_t fptr = f; // no address-of operator, implicit conversion
(*fptr)();

Your second example is doing exactly this, but using a temporary variable to hold the function pointer instead of a named local variable.

I prefer to use address-of when creating function pointers, the meaning is much clearer.

A related note: The function call operator will automatically dereference a function pointer if one is provided. So this also is legal:

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

That's pretty useful with templates, because the same syntax works whether you have a function pointer or a functor (object implementing operator()) passed in.

And neither shortcut works with pointer-to-members, there you NEED explicit address-of and dereference operators.


In C, @Mehrdad explains that all function calls use a function pointer.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

Just as an array type is almost entirely equivalent to the corresponding pointer-to-element type, a function type is entirely equivalent to the corresponding pointer-to-function type:

void (*func1)() = f;  // function type -> pointer-to-function type
void (*func2)() = &f; // pointer-to-function type -> pointer-to-function type

and also

void (*func)() = ...;
func();               // pointer-to-function type + function-call operator
(*func)();            // function type + function-call operator

So, in

(*f)();

you're dereferencing f (implicitly converted to &f), and then apply the function-call operator.

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90