3

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?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Aldan Creo
  • 686
  • 1
  • 5
  • 14
  • 1
    Same goes for an array. If `a` is an array, `a == &a` is true. Because arrays degenerate into a pointer to their first element when used as a pointer. – ikegami Nov 06 '20 at 16:58
  • @ikegami The comparision may become true, but `a` is not equivalent with `&a` if `a` is an array. `a` is an array and may be converted to a pointer that pointing at *the first element of* the array. On the other hand, `&a` is a pointer that pointing at the array itself. This is why `char s[32]; scanf("%31s", &s);` is not good. – MikeCAT Nov 06 '20 at 17:16
  • @MikeCAT I know, and it's not functions either. – ikegami Nov 06 '20 at 17:36

3 Answers3

4

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);.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • 1
    Great answer! I would only add that both statements compile to the same code in assembly, which makes sense according to your explanation as they are equivalent. – Aldan Creo Nov 06 '20 at 17:11
2

A function designator used in expressions is implicitly converted to pointer to the function.

So for example you could call your function like

( **********a )( 5 );

That is in this expression *a the function designator a is converted to pointer to the function. Applying the dereference operator * you again get a function designator that in turn is converted to pointer to the function in the expression **a. And so on.

From 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’’.

So in this assignment

func = &a; // Pointer to a pointer to a function

there is used the operator & (see the quote from the C Standard) that means that the function designator a is not converted to function pointer in this expression. And you do not have pointer to a function pointer as you wrote in the comment to the statement above.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

From the very documentation you've provided:

5.6 Calling Functions Through Function Pointers You can also call a function identified by a pointer. The indirection operator * is optional when doing this.

#include <stdio.h>

void foo (int i)
{
  printf ("foo %d!\n", i);
}

void bar (int i)
{
  printf ("%d bar!\n", i);
}

void message (void (*func)(int), int times)
{
  int j;
  for (j=0; j<times; ++j)
    func (j);  /* (*func) (j); would be equivalent. */
}

void example (int want_foo) 
{
  void (*pf)(int) = &bar; /* The & is optional. */
  if (want_foo)
    pf = foo;
  message (pf, 5);
}

So, The indirection operator * is optional when doing this. and /* The & is optional. */ comments says it all. They're optional. Why they are optional is explained by @MikeCat and @Vlad from Moscow

Hasan Manzak
  • 663
  • 6
  • 14