This is one of the classical examples of how convoluted C declarations can become.
To understand this declaration, it usually helps to introduce a typedef:
typedef void (*sighandler_t)(int);sighandler_t signal(int sig, sighandler_t func);
The typedef declares a pointer to a function (taking an int parameter and returning nothing).The function signal
can now be seen as a function that takes two parameters (an int and a pointer to a function) and returns a pointer to a function.
This can also be derived from the original declaration, but it takes a bit of practice. The usual way is to start at the identifier that names the outermost entity (signal
is this case):
signal
is a ...
Then you read right until you find an unmatched closing parenthesis or the end of the declaration: void (*signal
(int sig, void (*func)(int))(int)
signal
is a function taking ... returning ...
Now you can choose between parsing the parameters first, or the return value first. I will do the return value first. For that, you read backwards to find the matching open parenthesis: void
(signal( / ... */ ))(int)
signal
is a function taking ... returning a pointer to ...
Reading back and forth this way you get at successive stages:
signal
is a function taking ... returning a pointer to a (function taking ... returning ...)
signal
is a function taking ... returning a pointer to a (function taking ... returning void)
signal
is a function taking ... returning a pointer to a (function taking an int and returning void)
signal
is a function taking two parameters: (an int) and (a pointer to a function taking an int and returning void), and returning a pointer to a (function taking an int and returning void)