4

I am confused by the form of parameters for function pointers. The following two:

int fun(int (*g)())
{
    cout << g() << endl;
}

int fun(int g())
{
    cout << g() << endl;
}

Both these two definitions work well. But as you have noticed, there are some differences in the prototypes of these two functions:

  • the first one takes parameter int (*g)(),
  • while the second takes parameter int g().

My question is are there any difference between them?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
cheng
  • 2,106
  • 6
  • 28
  • 36

3 Answers3

4

In the second case, the function type adjusts to become pointer-to-function-type, which makes the both function identical.

int fun(int (*g)()); 
int fun(int g()); //same as above, after type adjustment

The C++03 Standard says in §13.1/3,

Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).

[Example:
    void h(int());
    void h(int (*)());  // redeclaration of h(int())
    void h(int x()) { } // definition of h(int())
    void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]

It's same as with array to pointer adjustement, with which we're more familiar:

int fun(int *a); 
int fun(int a[]);   //same as above, after type adjustment
int fun(int a[10]); //same as above, after type adjustment

All are same!

You can a detail answer by me here:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Can you explain why C++ decays int g() to pointer-to-function-type, the first one is pointer-to-function-type, but the second one is different from the first one, as you see, one more * symbol. For the array example it is easy to understand. – cheng Sep 18 '11 at 03:36
  • @Nawaz: There are two distinct rules in play here. An expression of function type is implicitly converted to a pointer to the function in most contexts (including an ordinary function call like `foo()`); this conversion is commonly called *decay*. A parameter declared to be of function type is *adjusted* to become pointer-to-function parameter. The two rules are related, but in principle the language could have one rule but not the other. Likewise for array-to-pointer decay and array-to-pointer parameter adjustment. – Keith Thompson Sep 18 '11 at 03:44
  • @cheng: For array, why is it easy to understand? Because you've seen this more frequently? Also, function type to pointer to function type conversion is allowed by the C++ Standard, in such situation. That is why,it decays. – Nawaz Sep 18 '11 at 03:45
  • @cheng: Read the updated answer, with quotation from the Standard. – Nawaz Sep 18 '11 at 03:45
2

You can't actually have a parameter of function type. A function parameter declared as if it were of type "function returning T" is adjusted to be of type "pointer to function returning T. So your two definitions are effectively identical. (C has the same rule.)

A similar rule applies to array parameter declarations. For example this:

int main(int argc, char *argv[]);

really means this:

int main(int argc, char **argv);
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • For the example you provided I can understand because "char *argv[]" and "char **argv" are indeed identical. But for int (*g)() and int g() how could they be the same. – cheng Sep 18 '11 at 03:31
  • Further more, if the two are identical, then the following definitions are also identical? typedef int (*funP) (void); typedef int funP2 (void); – cheng Sep 18 '11 at 03:32
  • @user508305: They're identical because a function parameter declaration is adjusted at compile time to a pointer-to-function declaration. It's similar to the adjustment rule that makes `char *argv[]` and `char **argv` equivalent (but *only* as a parameter declaration). – Keith Thompson Sep 18 '11 at 03:38
  • @user508305: No, those two typedefs are not identical. One makes `funP` a pointer type, the other makes it a function type. The adjustment rule applies *only* to parameter declarations, not to `typedef`s. – Keith Thompson Sep 18 '11 at 03:39
  • I'm curious why this was downvoted. I welcome constructive criticism. If you think I'm mistaken, please read the C and C++ standard references I cited in comments on Foo Bah's answer. – Keith Thompson Sep 18 '11 at 03:42
1

Most compilers (e.g. MSVC, g++) accept the second form as a shorthand for the first. Technically speaking you should always use the first form.

Foo Bah
  • 25,660
  • 5
  • 55
  • 79