5

I know when we use the name of a function as a value, the function is automatically converted to a pointer. look at following code:

int print(int a)
{
    return a;
}

int main()
{
    int (*p)(int) = print;
    int (*q)(int) = &print;

    cout << p(8) << endl;
    cout << (*p)(8) << endl;
}

why are int (*p)(int) = print; , print is a pointer, and int (*p)(int) = &print;, &print is an address to a pointer, equivalent?

On the other hand, when we use a pointer to a function to call the function, why are p(8) and (*p)(8) equivalent?

sydridgm
  • 1,012
  • 4
  • 16
  • 30
  • I guess it is just for convenience, that you dont have to explicitly dereference function pointers when using them to call the function. If you use `typedefs` you can work with function pointer without using any `*` which imho is quite nice – 463035818_is_not_an_ai Nov 04 '15 at 14:58
  • 2
    Possible duplicate of [How does dereferencing of a function pointer happen?](http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-function-pointer-happen) – Simon Kraemer Nov 04 '15 at 15:04
  • @SimonKraemer thank you. But the link only explain the dereference, my question also include the assignment of function pointer. – sydridgm Nov 04 '15 at 15:18

2 Answers2

3

print is not a pointer. Its type is int(int), not int(*)(int). This distinction is especially important in type deduction

auto& f = print;   //type of f is int(&)(int), not int(*(&))(int)
template<typename Func>
foo(Func& f);
foo(print);  //Func is deduced to be int(int), not int(*)(int)

Analogous to arrays, you cannot copy a function "by value", but you can pass around its address. For example,

int arr[4];     //the type of arr is int[4], not int*
int *a = arr;   //automatic array-to-pointer decay
int (*a)[4] = &arr;  //type match 
int (*p)(int) = print;  //automatic function-to-pointer decay
int (*p)(int) = &print; //type match

Now when you call print through p,

p(8)     //automatic dereferencing of p
(*p)(8)  //manual dereferencing of p
downhillFromHere
  • 1,967
  • 11
  • 11
  • your answer make some sense. but in the book **c++ primer 5th edition** and many other website tutorial said using function name as rvalue will convert it to a pointer. So I don't know whether your answer is a special condition for function pointer assignment. – sydridgm Nov 04 '15 at 16:43
  • @sydridgm They are correct. And they are referring to the function-to-pointer decay in my answer. – downhillFromHere Nov 04 '15 at 16:51
2

print is a function, but it is implicitly convertible to a function pointer type. Quoted from cppref:

Function to pointer
An lvalue of function type T can be implicitly converted to a prvalue pointer to that function. This does not apply to non-static member functions because lvalues that refer to non-static member functions do not exist.

So, in your case:

int (*p)(int) = print; // Conversion happens.
int (*q)(int) = &print; // Conversion does not happen.

Implicit conversion kicks in automatically when it is needed to make the program compile, and is not applied otherwise.

With respect to function calling, it is about the built-in function call operator (). According to cppref, the built-in function call operator is applicable to both an lvalue expression that refers to a function and a pointer to function. In your case:

p(8); // The function call operator is applied to a pointer to function.
(*p)(8); // The function call operator is applied to an lvalue reference to function.

For your reference (emphasis mine):

Built-in function call operator
A function call expression, such as E(A1, A2, A3), consists of an expression that names the function, E, followed by a possibly empty list of expressions A1, A2, A3, ..., in parentheses. The expression that names the function can be

a) lvalue expression that refers to a function
b) pointer to function
...

Lingxi
  • 14,579
  • 2
  • 37
  • 93