这两种风格的C函数指针定义有何不同?

时间:2016-03-10 17:23:30

标签: c pointers function-pointers

我不小心在不同的地方使用了两种不同风格的C函数指针定义,并决定编写一个最小程序来测试这些差异。

有问题的两种风格是:

int (comp (int))

int (*comp)(int)

我编写了一个最小程序,它将这两种样式用于同一个函数指针,一个用于函数的声明,另一个用于同一函数的定义 ,看看编译器会对它说些什么。

声明:

int a_or_b (int (*a_fn)(), int (b_fn()), int (*comp)(int));

定义:

int a_or_b (int (a_fn()), int (*b_fn)(), int (comp(int)))
{
    int out = a_fn ();
    if (comp (out))
        out = b_fn ();
    return out;
}

正如您所希望的那样,对于声明中的第一个参数,我使用了样式int (*a_fn)(),而在函数的定义中,我使用了样式int (a_fn ())。我用接下来的两个论点做了类似的事情。

我推测这些可能是不兼容的类型,这些样式可能是变量的pass-by-reference和pass-by-value赋值之间的区别,但是当我编译这个程序时,编译器默默地并愉快地编译它。没有错误,没有警告,没有。

由于我已经看过很多提倡第二种风格的教程,而我个人更喜欢第一种用于美学目的的风格,我感兴趣的是这两种风格之间的区别是什么,推荐使用。

完整代码示例:

#include <stdio.h>

int a ();
int b ();
int a_or_b (int (*a_fn)(), int (b_fn()), int (*comp)(int));

int a ()
{
    return 1;
}

int b ()
{
    return 2;
}

int comparison (int param)
{
    return param;
}

int a_or_b (int (a_fn()), int (*b_fn)(), int (comp(int)))
{
    int out = a_fn ();
    if (comp (out))
        out = b_fn ();
    return out;
}

int main (int argc, char **argv)
{
    printf ("%i\n", a_or_b (a, b, comparison));
    return 0;
}

2 个答案:

答案 0 :(得分:4)

在函数参数列表中,函数转换为函数指针。 C11标准,ISO / IEC 9899:2011,§6.7.6.3函数声明符(包括原型)说:

  

¶8参数声明为“函数返回类型”应调整为“指向函数返回类型的指针”......

因此,如上所述,参数都被视为“指向函数的指针”。不过,最好是自我保持。

请注意,函数无法返回函数:

  

¶1函数声明符不应指定函数类型或数组类型的返回类型。

在函数声明符(函数定义或函数声明的参数列表)之外,符号是不同的:

(refcount=3, is_ref=1),
object(stdClass)[1]
public 'test' => (refcount=1, is_ref=0),string 'bar' (length=3)

其中第一个声明(定义)一个名为int (*a_fn)(); int (b_fn()); 的变量 - 一个指向函数的指针,该函数返回带有未指定(但不是可变参数)参数列表的a_fn

其中第二个声明存在一个名为int的函数,它返回一个带有未指定(但不是可变参数)参数列表的b_fn(并且有一组多余的括号;它可以被写入int它意味着同样的事情。)

答案 1 :(得分:2)

当用作函数参数时,int (comp (int))int (*comp)(int)都是等效的。函数指示符转换为指向函数本身的指针。

C11-§6.3.2.1:

  

函数指示符是具有函数类型的表达式。除非它是sizeof运算符,_Alignof运算符, 65)或一元&运算符的操作数,否则函数指示符的类型为“函数返回” type“转换为具有类型的表达式”指向函数返回类型的指针。