I came across this piece of code and completely got lost interpreting its meaning.
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
What is a detailed explanation for the code at line 2?
I know that void and int are types, the *func is a pointer for a function, and the brackets are for priority. But I still don’t get the (*signal …), the (int), and the whole thing combined together. The more detailed, the better.
Probably I’ve known the meaning/effect of this declaration. But I had to make some more trials to help me understand what’s going on, as below:
1 #include <signal.h>
2 void (*signal)(int sig, void (*func)(int));
3 void (*signal)(int); // then void (signal)(int) again.
4 //void (*signal(int sig, void (*func)(int)))(int); //break this line into two lines above
5
6 int main(){}
In the above code, I broke void (*signal(int sig, void (*func)(int)))(int) into two lines. For line 3, I tried both void (*signal)(int) and void (signal)(int), with the same error result that indicated that I was trying to redeclare signal:
TestDeclaration.c:2: error: ‘signal’ redeclared as different kind of symbol
/usr/include/signal.h:93: error: previous declaration of ‘signal’ was here
TestDeclaration.c:3: error: ‘signal’ redeclared as different kind of symbol
/usr/include/signal.h:93: error: previous declaration of ‘signal’ was here
Now I know both the trials are incorrect ways of declaration, but why are they incorrect? Why is the original way of declaration NOT a redeclaration?
It’s the declaration of a function taking an
intand a pointer to a function (takingintreturning void) and returning a pointer to a function (takingintand returning void).Explanation, or guide to interpretation
You can interpret by treating everything in parentheses as a single entity and then working inwards using the "declaration follows usage" rule.
The entity in the brackets looks like a function taking
intand returningvoid.Stripping away the outer part:
So,
signaltakes some parameters and returns something that can be dereferenced (due to the leading*) to form a function takingintand returningvoid.This means
signalis a function returning a pointer to a function (takingintand returningvoid).Looking at the parameters it takes an
int(i.e.sig) andvoid (*func)(int)which is a pointer to a function (takingintand returningvoid).