如何使用函数指针返回函数指针?

3

我正在学习Unix中的信号处理,然后遇到了这个问题。

void (*signal(int sig, void (*func)(int)))(int);

我不理解这个原型以及如何返回一个指向函数的指针。
我还阅读了这篇答案:C语言中函数指针是如何工作的?,但对我来说并不清楚。
它应该返回一个函数指针,但我不明白它在哪里将返回类型指定为另一个函数指针。
我认为,如果我在函数定义中使用(*foo(int n)),则该函数foo(int n)的返回类型变为函数指针。这正确吗?
有没有更简单的例子呢?

2
此外:cdecl解释 - millimoose
此外,通过在函数签名后添加参数列表(其中已包含一个不相关的参数列表),返回类型变成了函数指针。比较void (*foo(int))(与void *foo(int)相同但不是void (*foo)(int))和void (*foo(int))(long)。换句话说:函数的返回类型是签名之外的内容,而不仅仅是其左侧的内容。 - millimoose
3个回答

3
因此,让我们看一下函数指针的声明方式。
return-type (*function-name)(parameter-list);

在您发布的声明中,有两种函数指针类型正在运行。第一个是传递到与signal原型匹配的函数的参数:
void (*signal(int sig, void (*func)(int)))(int);
//                     ^^^^^^^^^^^^^^^^^

让我们将函数指针类型重命名为handler,并为它提供自己的声明。

typedef void (*handler)(int);
void (*signal(int sig, handler func))(int);

现在我们可以解析声明的其余部分。 "内部"部分是实际的函数声明:
...signal(int sig, handler func)...

“外部”的含义是指它返回的函数指针:

void (...)(int);

这也是与我们的 handler 类型相同的函数指针类型,因此有了这个 typedef,我们可以像这样重新声明 signal 函数:

handler signal(int sig, handler func);

(更加美观。)

这也是一个“handler”,我错了吗? - glglgl
确实是这样。让我修改一下我的帖子,使它更加清晰明了。 - Adam Maras

1
void (*signal(stuff))(int)

将signal声明为返回一个以int为参数并返回void的函数指针。这里的stuff给出了传递给signal的参数。

(int sig, void (*func)(int))

也就是说,函数signal的第一个参数是int类型,第二个参数是一个以int作为参数并返回void的函数指针。

编辑:因此,如果您进行了某些调用——例如,

void foo (int x) {
    return;
}
void *bar = (*signal)(0, &foo);

那么bar将是一个指向函数的指针,接受一个整数参数并返回空值,因此可以按照以下方式调用:

(*bar)(0);

如果你调用一个函数指针,就不需要解引用*。只需执行bar(0)即可。 - glglgl
没错,但我发现它有助于记住大型项目中正在进行的事情。 - qaphla

1
我们可以使用 typedef 来简化函数指针的定义,这有助于您理解冗长而复杂的定义。
#include <stdio.h>
typedef void (*func)(int);
typedef void (*rtype)(int);

void myfunc(int a)
{
    printf("A is %d\n", a);
}

// thus signal can be defined as this
// exactly the same as in your question
rtype signal(int a, func handler)
{
    return myfunc;
}

int main()
{
    signal(0, 0)(12);
    return 0;
}

上面的代码应该输出:A is 12
希望能帮到你!

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