为什么 func 看起来和 C 中的 &func 一样?

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

根据 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?

相同

表达式中使用的函数指示符被隐式转换为指向函数的指针。

例如,您可以像这样调用您的函数

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

即在此表达式 *a 中,函数指示符 a 被转换为指向函数的指针。应用取消引用运算符 *,您将再次获得一个函数指示符,该指示符又被转换为指向表达式 **a 中的函数的指针。等等。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

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

所以在这个作业中

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

使用了运算符 &(请参阅 C 标准中的引文),这意味着函数指示符 a 不会在此表达式中转换为函数指针。而且你没有指向函数指针的指针,正如你在上面语句的注释中所写的那样。

N1570 6.3.2.1 左值、数组和函数指示符说:

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

此处 a*func 函数指示符 因为它们具有函数类型。 &a 中的 a 未转换为指针,因为它是一元 & 运算符的操作数,并且指向函数的指针由 & 运算符检索。 另一方面,func = a;中的a根据这个规则转换为指向函数的指针。 因此,此代码中的 a&a 是等价的。

另外func(x);中的func也是按照这个规则转换为指针的。

(*func)(x); 是:

  1. func按照这个规则转换为指针
  2. 指针在 *func
  3. 中被 * 取消引用
  4. *func按照这个规则转换为指针

因此 (*func)(x); 等价于 func(x);.

根据您提供的文档:

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

所以,The indirection operator * is optional when doing this./* The & is optional. */ 评论说明了一切。它们 可选 。来自莫斯科的@MikeCat 和@Vlad 解释了为什么它们是可选的