Search code examples
cfunctionpointersfunction-pointersimplicit-conversion

Why does it seem that func is the same as &func in C?


According to the GNU C manual, functions can be called using function pointers like so:

func (j);  /* (*func) (j); would be equivalent. */

So my reasoning here is: func itself is a pointer to the func(int) function. When you call func(j), you are implicitly accessing the value of the pointer func (you are moving to the memory location where func is), in the same way as when you have a pointer to an integer, for example, and you access the value stored in that position of the memory using *. That would be consistent with the fact that you can call that same function using (*func)(j).

In fact, in cprogramming.com, they say you can have a pointer to a pointer of a function. So I am therefore guessing they work like any other kind of pointers.

But if that's the case, why is it that this code works?

#include <stdlib.h>
#include <stdio.h>

void a(int n) {
    printf("%d\n", num);
}

int main() {
    int x = 5;
    void (*func)(int); // Declare a pointer to a function
    func = &a; // Pointer to a pointer to a function
    (*func)(x); // Calls the function (why?)
    func = a; // Pointer to a function
    (*func)(x); // Calls the function (makes sense)
}

Moreover, if you call:

printf("%s\n", (&a == a) ? "True" : "False");

It prints True!

I am sure that &foo is not the same as &&foo, for example, so why does it seem to be the case that func is the same as &func?


Solution

  • N1570 6.3.2.1 Lvalues, arrays, and function designators says:

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

    Here a and *func are function designators because they have function type. a in &a is not converted to a pointer because it is the operand of the unary & operator and the pointer to the function is retrieved by the & operator. On the other hand, a in func = a; is converted to the pointer to the function according to this rule. Therefore a and &a in this code are equivalent.

    Also func in func(x); is converted to the pointer according to this rule.

    (*func)(x); is:

    1. func is converted to the pointer according to this rule
    2. The pointer is dereferenced by * in *func
    3. *func is converted to the pointer according to this rule

    Thus (*func)(x); is equivalent to func(x);.