-3

I am a college student. I saw this way of writing in Expert C Programming. I don't understand why the function pointer can be called like this.

#include <stdio.h>

void fun(){}

int main(int argc, char const *argv[])
{
    void (*p)() = fun;
    (************************************************************************p)();
    return 0;
}
  • 1
    It's just doing an absurd amount of pointer dereferencing and then probably segfaulting. – richardec Feb 09 '22 at 17:02
  • dont trying to understand it before you understand pointer, after you understand pointer, then you would understand it immediately – 0nepeop1e Feb 09 '22 at 17:08
  • [Here](https://stackoverflow.com/q/4955198/6273251) is a post that thoroughly explains dereferencing pointers. [Here](https://stackoverflow.com/q/758673/6273251) is one that explains multilevel pointer dereferencing. [Here](https://stackoverflow.com/q/840501/6273251) is a post explaining how function pointers work. I think that's all you need to know. – Random Davis Feb 09 '22 at 17:10

2 Answers2

5

This works because of how function designators and function pointers work.

When a function pointer is dereferenced, the result is a function designator. However, in most contexts a function designator is converted to a function pointer.

This behavior is spelled out in section 6.3.2.1p4 of the C standard:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, 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’’.

What this means is that given function pointer p, *p is a function designator but is then converted back to a function pointer wherever it is used. This means a function pointer can be dereferenced (essentially) an unlimited number of times and yield the same result.

In addition, the function call operator () actually expects a function pointer as its argument. So if you were to execute fun(), fun would first be converted to a function pointer as per the above rule then the function call operator is applied to that function pointer.

Put those together, and that's what this code is demonstrating.

dbush
  • 186,650
  • 20
  • 189
  • 240
0

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 (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; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

So as p is a pointer to a function then the expression *p denotes the function pointed to by the pointer p. If to apply the unary operator * to the expression *p like **p the function designator that is obtained by the expression *p is implicitly converted to pointer to the function and the expression **p again yields the function designator and so on for other applications of the operator *.

Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303