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

杀马特。学长 韩版系。学妹 提交于 2020-12-26 03:50:55

问题


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?


回答1:


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




回答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.




回答3:


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



来源:https://stackoverflow.com/questions/64718604/why-does-it-seem-that-func-is-the-same-as-func-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!