这是一个简单而细腻的问题。有人可以解释a和b之间的区别吗?
void (*a)(int x, int y)
void (*b(int x, int y))(int)
这个问题来自以下Linux函数声明:
void (*signal(int sig, void (*func)(int)))(int);
以下程序是一个很好的演示。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch(int sig)
{
printf("OUCH! - I got signal %d\n", sig);
signal(SIGINT, SIG_DFL);
}
void (*g())(int) // just like the b
{
return ouch;
}
int main()
{
void (*f)(int); // just like the a
f=g();
signal(SIGINT, f);
while(1)
{
printf("Hello, world!\n");
sleep(1);
}
}
答案 0 :(得分:10)
C的设计者选择以一种方式命名他们的类型,使用该类型的用例尽可能地匹配使用该类型获取值的方式。因此,例如,当你有一个像
这样的声明时int a;
您可以说a
获得int
。如果您有类似
int *a;
然后,您必须通过撰写a
来取消引用*a
以获得int
。
您可以使用类似的,虽然更复杂的逻辑来解码您发布的类型。让我们从
开始void (*a)(int x, int y)
这说明如果您取消引用a
(通过撰写*a
),那么您剩下的就是
void (int x, int y)
这是一个函数,它接收两个int
并返回void
。换句话说,您可以将a
视为指向函数的指针;一旦被解除引用,你就会恢复功能。
现在这个野兽:
void (*b(int x, int y))(int)
这个比较棘手。这个想法如下。如果你取b
并将两个参数传入其中,那么你会得到一些看起来像这样的东西:
void (*)(int)
指向int
并返回void
的函数的指针。换句话说,b
是一个带有两个参数的函数,然后返回一个带有一个参数并返回void
的函数指针。
解码这些类型有点棘手,所以通常你不会以这种方式编写,而是使用typedef
来简化操作。例如,这个typedef:
typedef void (*FunctionTakingTwoInts)(int, int);
表示可以使用FunctionTakingTwoInts
定义一个函数指针,该函数指针指向一个函数,该函数接收两个int
并返回void
。从这里开始,a
的声明简化为
FunctionTakingTwoInts a;
同样,在b
的情况下,让我们定义类型
typedef void (*FunctionTakingOneInt)(int);
现在,我们可以将b
重写为
FunctionTakingOneInt b(int x, int y);
我认为,实际上这种类型的含义要清楚得多。
希望这有帮助!
答案 1 :(得分:3)
简短版本:a
声明指向函数的指针。 b
声明一个返回指向函数的指针的函数。
更长版本:您知道以下模式来声明指向函数的指针
void (*f)(int x, int y)
现在,取“f”,然后修改它。例如,将其设为数组
void (*f[3])(int x, int y)
现在,您没有指向函数的指针,而是有一个指向函数的指针数组。现在,如果您将其修改为函数而不是数组,则已将第一个声明转换为第二个声明
void (*f(void))(int x, int y)
您已将其修改为返回指向函数的指针的函数。您的声明不是没有像这种情况那样的参数,而是有两个参数。其中一个是int
,另一个是另一个指向函数的指针。
使用typedef比组合C声明符更容易。
// your example
typedef void signal_fn(int);
signal_fn *signal(int sig, signal_fn *func);
// my example above
typedef void f_fn(int x, int y);
f_fn *f(void);
答案 2 :(得分:1)
将(*a)
替换为foo:
void foo(int x, int y);
a
是指向类似函数的指针。
同样,将(*b(int x, int y))
替换为foo:
void foo(int);
b(int x, int y)
返回指向类似函数的指针。
答案 3 :(得分:0)
http://cdecl.org/可以为这样的声明提供很好的帮助。不幸的是,它不处理命名的函数参数,因此必须删除它们。喂养
void( signal(int,void()(int)))(int)
给出:
将signal声明为函数(int,指向函数的指针(int)返回void)返回指向function(int)的指针返回void