这两个声明有什么区别?

smw*_*dia 2 c types function-pointers

这是一个简单而细腻的问题.有人可以解释a和b之间的区别吗?

void (*a)(int x, int y)
void (*b(int x, int y))(int)
Run Code Online (Sandbox Code Playgroud)

这个问题来自以下Linux函数声明:

void (*signal(int sig, void (*func)(int)))(int);
Run Code Online (Sandbox Code Playgroud)

以下程序是一个很好的演示.

#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);
   }
}
Run Code Online (Sandbox Code Playgroud)

tem*_*def 10

C的设计者选择以类型的用例尽可能匹配使用该类型获取值的方式来命名其类型.所以,例如,当你有一个类似的声明时

int a;
Run Code Online (Sandbox Code Playgroud)

你可以说a要得到一个int.如果你有类似的类型

int *a;
Run Code Online (Sandbox Code Playgroud)

然后你必须a通过写作取消引用*a来获得一个int.

您可以使用类似的,虽然更复杂的逻辑来解码您发布的类型.让我们开始吧

void (*a)(int x, int y)
Run Code Online (Sandbox Code Playgroud)

这说明如果你取消引用a(通过写作*a),那么你留下的东西就是这样

void (int x, int y)
Run Code Online (Sandbox Code Playgroud)

这是一个接受两个ints并返回的函数void.换句话说,您可以将其a视为指向函数的指针; 一旦解除引用,你就会恢复功能.

现在这个野兽:

void (*b(int x, int y))(int)
Run Code Online (Sandbox Code Playgroud)

这个比较棘手.这个想法如下.如果你接受b并传入两个参数,那么你会得到一些看起来像这样的东西:

void (*)(int)
Run Code Online (Sandbox Code Playgroud)

这是一个指向函数的指针int并返回void.换句话说,b是一个带有两个参数的函数,然后返回一个带有一个参数并返回的函数指针void.

解码这些类型有点棘手,所以通常你不会用这种方式编写,而是typedef用来简化事情.例如,这个typedef:

typedef void (*FunctionTakingTwoInts)(int, int);
Run Code Online (Sandbox Code Playgroud)

说你可以FunctionTakingTwoInts用来定义一个函数指针,指向一个接受两个ints并返回的函数void.从这里开始,声明a简化为

FunctionTakingTwoInts a;
Run Code Online (Sandbox Code Playgroud)

同样,在这种情况下b,让我们定义类型

typedef void (*FunctionTakingOneInt)(int);
Run Code Online (Sandbox Code Playgroud)

现在,我们可以重写b

FunctionTakingOneInt b(int x, int y);
Run Code Online (Sandbox Code Playgroud)

从这个角度来看,我认为这种类型的实际意义要清楚得多.

希望这可以帮助!

  • 天啊,你的答案就是这样一个大师! (2认同)