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

8

我发现自己不小心在不同的地方使用了两种不同风格的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 ())。我对接下来的两个参数也做了类似的处理。

我猜想这些可能是不兼容的类型,这些样式可能是变量按引用传递和按值传递分配之间的区别,但当我编译此程序时,编译器默默地并且高兴地将其编译通过。没有错误,没有警告,什么都没有。

由于我看过很多教程推荐使用第二种样式,而我个人更喜欢第一种样式出于美学目的,因此我很想知道这两种样式之间的区别以及哪种样式被推荐。

完整代码示例:

#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
在函数参数列表中,“函数”会被转换为函数指针。根据ISO/IEC 9899:2011 §6.7.6.3函数声明符(包括原型),规定如下:¶8将参数声明为“返回类型的函数”的声明应调整为“返回类型的函数指针”。 - Jonathan Leffler
2个回答

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

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

因此,按照书写方式,所有参数都被视为“指向函数的指针”。然而,最好保持自洽性。

请注意,函数不能返回一个函数:

¶1 函数声明符不得指定函数类型或数组类型作为返回类型。

在函数声明符外(函数定义或函数声明的参数列表),符号表示不同:
int (*a_fn)();
int (b_fn());

第一个声明定义了一个名为 a_fn 的变量 —— 一个指向返回 int 类型且参数列表未指定(但不是可变参数)函数的指针。
第二个声明表明存在一个名为 b_fn 的函数,它返回一个未指定(但不是可变参数)参数列表的 int 类型值(并且有一个多余的括号,可以写成 int b_fn();,意思相同)。

这个答案似乎涵盖了所有情况。谢谢! - Marcus Harrison

2

当作为函数参数使用时,int (comp (int))int (*comp)(int)是等效的。函数设计符号被转换为指向函数本身的指针。

C11-§6.3.2.1:

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


谢谢你的回答!这两种风格有时会表现出不同的行为吗? - Marcus Harrison
3
在最高层面上,“int (comp(int))”是一个名为“comp”的函数的原型,它接受并返回一个“int”,而“int (*comp)(int)”是指向函数的指针。 - Tavian Barnes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接