C函数指针调用语法

giv*_*ivi 3 c function-pointers

假设有一个函数指针:

void func(float a1, float a2) {

}

void (*fptr)(float, float) = &func;
Run Code Online (Sandbox Code Playgroud)

这两行之间是否有任何区别(编译和编译工作)?

(*fptr)(1,2);
fptr(1,2);
Run Code Online (Sandbox Code Playgroud)

我想第二个版本只是第一个版本的捷径,但我想确保自己.更重要的是标准行为?

Mic*_*urr 6

是的,它是标准行为,适用于所有C编译器.

函数调用实际上总是通过指向函数的指针来完成:

6.5.22"函数调用":

表示被调用函数的表达式(脚注77)应具有指向函数的类型指针返回void或返回除数组类型之外的对象类型

如脚注77所示,当使用函数调用表达式时,"正常"函数标识符实际上转换为指向函数的指针:

脚注77:

通常,这是转换作为函数指示符的标识符的结果.

有趣的是,取消引用函数指针(或转换为函数指针的函数指示符)会产生函数的函数指示符,该函数指示符将被转换回函数调用表达式的函数指针.因此,您可以取消引用函数指针(或正常的函数名称),但不必.

6.5.3.2/4"地址和间接运营商":

The unary * operator denotes indirection. If the operand points to a function, the result is a function designator
Run Code Online (Sandbox Code Playgroud)

因此,就标准而言,对于您的示例:

(*fptr)(1,2);
fptr(1,2);
Run Code Online (Sandbox Code Playgroud)

第二个并不是简写 - 这是编译器所期望的.实际上,第一个例子实际上只是一个更冗长的方式来表达与第二个相同的东西.但有些人可能更喜欢第一种形式,因为它更清楚地表明正在使用指针.生成的代码应该完全没有区别.

标准措辞的另一个结果是您也可以取消引用正常的函数名称:

func(1,2);
(*func)(1,2);  // equivalent to the above
Run Code Online (Sandbox Code Playgroud)

并不是说我能想到这样做真的有任何可辩护的意义.


Kei*_*son 6

他们做同样的事情.

函数调用的前缀始终是指向函数类型的表达式.

指针类型的表达式,例如声明的函数的名称.隐式转换为指向该函数的指针,除非它是一元的操作数"&"(无论如何产生函数的地址)或sizeof(这是非法的而不是产生指针的大小).

这条规则的结果是所有这些:

&func
func
*func
**func
Run Code Online (Sandbox Code Playgroud)

是等价的.它们都评估函数的地址,并且它们都可以(如果适当地括号括起)用作函数调用的前缀.