1

I was reading Alex Allain's tutorial on function pointers (http://www.cprogramming.com/tutorial/function-pointers.html) in which he describes the syntax of receiving a function argument as such:

void doSomething(int (*GetNumber)(Player p) = myFunct) {

}

Then I was reading Accelerated C++, which shows the following syntax:

map<string, vector<int> >
xref(istream& in, vector<string> find_words(const string&) = split) {

}

Is there a difference between the two approaches? That is, A versus B:

A:

void doSomething(int (*GetNumber)(Player p) = myFunc) {

}

B:

void doSomething(int GetNumber(Player p) = myFunc) {

}
imreal
  • 10,178
  • 2
  • 32
  • 48

2 Answers2

4

There is no difference because functions passed by values as arguments are implicitly converted to pointers. So these two declarations

void doSomething(int (*GetNumber)(Player p) );

void doSomething(int GetNumber(Player p) );

declare the same function.

You could write the declarations also as

void doSomething(int (*)(Player) );

void doSomething(int( Player ) );

It is the same as the equivalence of the following declarations

void f( int a[] );

and

void f( int *a );

and

void f( int a[10] );

and even

void f( int a[100] );

They all declare the same function.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Agree with above. There is no implicit conversion to pointer type in the array example. – thor Feb 18 '14 at 01:17
  • 2
    @Dave You are wrong relative to arrays. The declarations I showed are equivalent. For example these declarations void f( int * ); void f( int[] ); void f( int[10] ); declare the same function. – Vlad from Moscow Feb 18 '14 at 01:21
  • @Ting L You are wrong. The example of the declarations of functions with an array and with pointer declare the same function. – Vlad from Moscow Feb 18 '14 at 01:23
  • You probably misunderstood me and the other comment. The two function declarations you gave are equivalent, yes. The two array declarations are equilvant, yes. But they are equivalent for different reasons. You claimed that the two cases of equivalence are for the same reasons. That's where I don't agree. – thor Feb 18 '14 at 01:30
  • Quoting your original answer: " ... declare the same function. It is the same as the equivalence of the following declarations void f( int a[] ); ..." – thor Feb 18 '14 at 01:31
  • @Ting L I did not say about the reason. But in any case the reason is the same: functions and arrays are converted to pointers. What is the other reason? – Vlad from Moscow Feb 18 '14 at 01:32
  • Well, in the case of functions, it's as if pointer is removed from the type (as if from A to A*). This is not the case for the arrays. – thor Feb 18 '14 at 01:34
  • @Ting L It is your personal fantasies. I did not say that. – Vlad from Moscow Feb 18 '14 at 01:38
  • Maybe. I just think it's confusing and it did lead to multiple persons to think that way. It seems that you edited your answer promptly in response to those comments. So I have no more problems. – thor Feb 18 '14 at 01:40
  • For your reference, quoting http://stackoverflow.com/a/2795596/683218, a (minor) nuance regarding de-referencing a function vs. an array: "An array value is also converted to a pointer in an lvalue context, but it is converted to a pointer to the element type, not to a pointer to the array. Dereferencing it will therefore give you an element, not an array, and the madness you show doesn't occur." – thor Feb 18 '14 at 02:02
  • @Ting L I know all this. I said that "it is the same as EQUIVALENCE of the following declarations" It is all clear enough. – Vlad from Moscow Feb 18 '14 at 02:06
2

There are two distinct language rules involved here.

One is that a parameter that appears to be of function type is adjusted at compile time to a pointer to the function:

After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

That's the rule that makes these function declarations:

void foo(void (*p)());

and

void foo(void (p)());

equivalent.

The other is that an expression of function type is, in most contexts, implicitly converted to a pointer to the function:

An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.

Given a function declaration:

void func();

this rule is what makes all these calls:

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

equivalent. On the last one, the expression func is of function type, so it's converted to a pointer. The inner * dereferences that pointer yielding an expression of function type, which is then implicity converted to a pointer again. And the outer * does the same thing.

In fact, the expression foo is also converted to a pointer -- which is just what the function-call operator requires as the operand preceding the (.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631