8

I was wondering about the specific reason for which it is possible to use multiple times the dereferencing operator * when we want to assign a function to a function pointer.
As an example, the following code perfectly compiles and runs:

#include <iostream>

void f() { std::cout << "Hello World!" << std::endl; }

int main() {
    void(*f_ptr)(void) = ***************************************f;
    f_ptr();
    return 0;
} 
FdeF
  • 552
  • 4
  • 10

3 Answers3

11

Functions and references to functions decay to a function pointer whenever necessary. There is no dereference operator defined for functions but there is one for function pointer: the function or reference to function happily decays to a pointer just to become derefernced again.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
4

On the one hand, according to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)

4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator65) or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.

and according to the C++ Standard (4.3 Function-to-pointer conversion)

1 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

On the other hand according to the C Standard(6.5.3.2 Address and indirection operators)

4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator;

and the C++ Standard (5.3.1 Unary operators)

1 The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.”

Thus there are recursive conversions.at first from the function designator to pointer and then from the pointer to the function designator (or as written in the C++ Standard to lvalue referring the function) and again from the function designator or lvalue to function pointer and so on.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
-4

You are initialising f_ptrto be a pointer to a pointer to a pointer... to a pointer. Hence you can chain as many as you like, the address of the parent pointer will simply hold the address of its child pointer. Double pointers are often used to initialise variables in a function.

TomJ
  • 424
  • 3
  • 14
  • a `double**` is not the same as a `double*`. But for function pointers, this difference doesn't really apply. – rubenvb Dec 12 '16 at 09:58
  • No I know, I meant double pointer to mean double** otherwise I'd have said a pointer to a double type – TomJ Dec 12 '16 at 10:01
  • 1
    I understand, but the only case where a `T**` behaves the same as a `T*` is when `T` is a function (pointer/reference) type. So no your answer does not explain this phenomenon. – rubenvb Dec 12 '16 at 10:04
  • Ahh ok, forgive me, I understand – TomJ Dec 12 '16 at 10:06
  • @TomJ Notice that this code line: `void(**f_ptr)(void) = **f;` does not compile at all (if cut and pasted in the question code). – FdeF Dec 12 '16 at 10:11