Looking at it from the other side, how do you create such a declaration? You can do it by following two rules:
- To declare a function (with some argument list) returning
T
, first declare func
as T
. Then add the parameter list (wrapped in parentheses) after func
.
- To declare a pointer to
T
, first declare ptr
as T
. Then add (*
before and )
after ptr
. Optionally, if the token following (*ptr)
is not (
or [
, you can remove the parens you just added (leaving just *ptr
).
(func
and ptr
are just placeholders. You can use any identifier you want.)
signal
is a function (we'll deal with the parameters later) returning a pointer to a function (of some parameters) returning void
. To declare this, we need to start at the end and declare signal
as void
(yes, I know that's not allowed):
void signal;
The next step is "... function (of some parameters) returning void
", so we apply rule #1:
void signal( /* some parameters */ );
The next step is "... a pointer to [that function]", so we apply rule #2:
void (*signal)( /* some parameters */ );
We can't remove the parens in (*signal)
because the following token is (
.
The next step is "... a function (we'll deal with the parameters later) returning [that pointer]", so we apply rule #1:
void (*signal( /* to be dealt with later */ ))( /* some parameters */ );
That's the complete skeleton. Now let's take a look at the parameter lists.
The some parameters part is what the function-that-signal
-returns-a-pointer-to accepts. Which is just an int
:
void (*signal( /* to be dealt with later */ ))( int );
The to be dealt with later part is what signal
itself takes, which is two parameters:
- a signal number,
int
- a signal handler, a pointer to a function (taking an
int
) returning void
#1 is easy: int sig
.
#2 can be done "backwards" again:
void func; // func is void
Applying rule #1:
void func(int); // func is a function returning void
Applying rule #2:
void (*func)(int); // func is a pointer to a function returning void
Plugging our parameters in the declaration of signal
finally gives us:
void (*signal( int sig, void (*func)(int) ))( int );
This is exactly the declaration you were struggling to decipher: signal
is a function (taking sig
, an int
, and func
, a pointer to a function taking an int
and returning void
) returning a pointer to a function taking an int
and returning void
.
This answer might not make it easier to read those declarations, but now you'll be able to create your own monstrosities of this kind. :-)
PS: If you want to incorporate arrays as well, there's a third rule:
- To declare an array (of size
N
) of T
, first declare arr
as T
. Then add [N]
after arr
.