这两个函数指针调用语法变量如何工作?

时间:2014-01-23 18:40:14

标签: c

我对C来说比较新,并且发现下面对函数指针的两个调用都编译并且正常工作很有趣。一个有和没有在调用它之前取消引用函数指针。

#include <stdio.h>
#include <stdlib.h>

void func() {
    puts("I'm a func");
}
int main(void) {
    void (*f)() = func;
    f();
    (*f)();
    return EXIT_SUCCESS;
}

我想我明白(*f)()是&#34;官员&#34;调用函数指针的方法,但为什么简单地调用f()有效?最新C版本的语法糖是什么?

4 个答案:

答案 0 :(得分:8)

这是一段语法/语义糖,它具有AFAIK,从最早的C版开始就有效。如果你把函数看作是代码的指针,这是有意义的。

使函数指针以这种方式工作所需的唯一特殊规则是间接一个函数指针返回相同的指针(因为你不能操纵标准C中的代码):当f是函数指针时,然后f == (*f) == (**f)等。

(旁白:注意void (*f)()之类的声明。空参数列表表示仅在返回类型上匹配的旧式C89前函数声明。优先选择void (*f)(void)类型。)

答案 1 :(得分:4)

在C语言中,您可以将您的功能称为:

f();
(*f)();
(**f)();
(********f)();
(*****************************f)();  

都是有效的。在C中,取消引用或获取函数的地址只是求值为指向该函数的指针,并且取消引用函数指针只会计算回函数指针。 C的设计方式是函数名称标识符和变量保持函数的指针都是相同的:地址到CODE内存。它允许通过在标识符或变量上使用call ()语法跳转到该内存 最后但最不重要的标准说:

C11:6.3.2.1:

  

4函数指示符是具有函数类型的表达式。除非它是   sizeof运算符,_Alignof运算符,65)或一元&运算符的操作数,a   类型为''函数返回类型''的函数指示符将转换为类型为''指向函数返回类型''的表达式。

答案 2 :(得分:4)

函数调用表达式的形式总是“函数指针”,“圆括号”,“参数”,“圆括号”。为了不必每次 1 拼出(&printf)("Hello World\n"),都有一个单独的规则,表示函数的表达式衰减到相应的函数指针。

由于可以取消引用函数指针以提供再次表示函数的表达式,这将再次衰减,因此您可以继续解除引用并且会有很多衰减:

(&f)();   // no decay (decay does not happen when the expression
          //           is the operand of &)
f();      // one decay
(*f)();   // two decays
(**f)();  // three decays


1)早期的Perl具有类似的函数语法。

答案 3 :(得分:4)

C 2011标准在第6.3.2.1条第4段中说明:

  

除非是 sizeof运算符的操作数, _Alignof 运算符或一元&amp; 运算符,否则为函数指示符类型''函数返回类型''被转换为一个表达式,其类型为''指向函数返回 type ''的指针。

这意味着,如果f指定了某个功能,那么,在f()之类的通话中,f会自动转换为&f,从而产生{{1} }}。这实际上是调用函数的“正确”方法,因为函数调用表达式需要一个指向函数的指针。

现在考虑(&f)()中发生的事情。 *f会自动转换为f,因此我们&f。在此表达式中,*&f运算符的结果是函数*;它只是反转f执行的操作。因此&*&f相同。我们可以无限期地重复此操作:f会自动转换为**f**&f,会自动转换为*f,即*&f,这是f自动转换为&f