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.