问题描述
根据GNU C manual,可以使用函数指针来调用函数,如下所示:
func (j); /* (*func) (j); would be equivalent. */
所以我在这里的理由是:func
本身是指向func(int)
函数的指针。调用func(j)
时,您将隐式访问指针func
的值(您将移至func
所在的存储位置),其方式与使用指针时相同例如,将其设置为整数,然后使用*
访问存储在内存中该位置的值。这与您可以使用(*func)(j)
调用同一函数的事实是一致的。
事实上,在cprogramming.com中,他们说您可以具有指向函数指针的指针。因此,我因此猜测它们的工作原理与任何其他类型的指针一样。
如果是这种情况,为什么这段代码可以正常工作?
#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)
}
此外,如果您致电:
printf("%s\n",(&a == a) ? "True" : "False");
它将打印True
!
例如,我确定&foo
与&&foo
不同,因此为什么在 func
相同的情况下为什么为&func
?
解决方法
N1570 6.3.2.1左值,数组和函数指示符表示:
4函数标识符是具有函数类型的表达式。除 当它是sizeof运算符的操作数时,_Alignof 运算符(65)或一元&运算符(类型为 “函数返回类型”被转换为具有 类型为“函数返回类型的指针”。
此处a
和*func
是功能指示符,因为它们具有功能类型。 a
中的&a
不会转换为指针,因为它是一元&
运算符的操作数,并且该函数的指针由&
运算符检索。
另一方面,a
中的func = a;
根据此规则转换为指向函数的指针。
因此,这段代码中的a
和&a
是等效的。
func
中的func(x);
也会根据此规则转换为指针。
(*func)(x);
是:
-
func
根据此规则转换为指针 -
*
中的*func
取消了指针的引用 -
*func
根据此规则转换为指针
因此(*func)(x);
等同于func(x);
。
表达式中使用的函数指示符被隐式转换为指向函数的指针。
例如,您可以像这样调用函数
( **********a )( 5 );
在此表达式*a
中,功能指示符a
被转换为指向该函数的指针。应用取消引用运算符*
,您将再次获得一个函数指示符,该函数指示符又转换为表达式**a
中指向该函数的指针。依此类推。
根据C标准(6.3.2.1左值,数组和函数指示符)
4函数标识符是具有函数类型的表达式。 除非它是sizeof运算符的操作数(65)或一元& 操作符,类型为“功能返回类型”的功能指示符 转换为类型为“函数指针”的表达式 返回类型”。
所以在这项作业中
func = &a; // Pointer to a pointer to a function
使用了运算符&
(请参见C标准的引用),这意味着函数标识符a
不会在此表达式中转换为函数指针。而且,您没有指向上述语句的注释中所写的函数指针。
根据您提供的文档:
5.6通过函数指针调用函数 您也可以调用由指针标识的函数。间接操作符*在执行此操作时是可选的。
#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); }
因此,The indirection operator * is optional when doing this.
和/* The & is optional. */
的评论说明了一切。它们是可选。来自莫斯科的@MikeCat和@Vlad解释了为什么它们是可选的