问题
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:
func
is converted to the pointer according to this rule- The pointer is dereferenced by
*
in*func
*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