What's the difference between these 2 declarations?
Here's a simple and delicate question. Could someone explain the difference between a and b?
void (*a)(int x, int y)
void (*b(int x, int y))(int)
This question arise from the following Linux function declaration:
void (*signal开发者_StackOverflow社区(int sig, void (*func)(int)))(int);
Solution
The following program makes a good demo.
#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);
}
}
The designers of C chose to name their types in a way that the use case of the type matches, as closely as possible, the way in which you use that type to get a value. So, for example, when you have a declaration like
int a;
You can just say a
to get an int
. If you have a type like
int *a;
Then you have to dereference a
by writing *a
to get an int
.
You can use similar, albeit more complex, logic to decode the types you posted. Let's start with
void (*a)(int x, int y)
This says that if you dereference a
(by writing *a
), then what you're left with is something that looks like
void (int x, int y)
Which is a function taking in two int
s and returns void
. In other words, you can think of a
as a pointer to a function; once dereferenced, you get back the function.
Now for this beast:
void (*b(int x, int y))(int)
This one's trickier. The idea is as follows. If you take b
and pass in two arguments into it, then you get back something that looks like this:
void (*)(int)
Which is a pointer to a function taking in an int
and returning void
. In other words, b
is a function that takes two arguments, then returns a function pointer that takes one argument and returns void
.
It's somewhat tricky to decode these types, so often you don't seem them written this way and instead use typedef
to simplify things. For example, this typedef:
typedef void (*FunctionTakingTwoInts)(int, int);
Says that you can use FunctionTakingTwoInts
to define a function pointer that points at a function that takes in two int
s and returns void
. From here, the declaration of a
simplifies down to
FunctionTakingTwoInts a;
Similarly, in the case of b
, let's define the type
typedef void (*FunctionTakingOneInt)(int);
Now, we can rewrite b
as
FunctionTakingOneInt b(int x, int y);
From which, I think, it's much clearer what the type actually means.
Hope this helps!
Short version: a
declares a pointer to a function. b
declares a function that returns a pointer to a function.
Longer version: You know the following pattern to declare a pointer to a function
void (*f)(int x, int y)
Now, take the "f", and modify it. For example, make it an array
void (*f[3])(int x, int y)
Now, instead of having a pointer to a function, you have an array of pointer to functions. Now if you instead modify it to be a function rather than an array, you have transformed the first declaration to the second declaration
void (*f(void))(int x, int y)
You have modified it to be a function that returns a pointer to a function. Instead of having no parameter like in this case, your declaration has two parameters. One of which is an int
and the other of which is another pointer to function.
It's easier to use typedefs than to combine the C declarators for doing this though.
// 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);
Replace (*a)
with foo:
void foo(int x, int y);
a
is a pointer to a function like that.
Likewise, replace (*b(int x, int y))
with foo:
void foo(int);
b(int x, int y)
returns a pointer to a function like that.
http://cdecl.org/ can be a good help for declarations like this. Unfortunately, it doesn't handle named function parameters, so those have to be removed. Feeding in
void (signal(int , void ()(int)))(int)
gives:
declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void
精彩评论