tags:

views:

279

answers:

3

I came across this piece of code and completely get lost for it meaning.

#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

So would someone like to explain the code line 2 at some detail? I know that void and int are types, that *func is a pointer for a function, and that 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. But if you could not provide a lot of detail, a few words are also welcome.


Thanks to all the explanation, probably I've known the meaning/effect of this declaration. But I make some more trial 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 indicates 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 trial are incorrect ways of declaration, but why are they incorrect? Why is the original way of declaration NOT a Redeclaration?

Well, I didn't notice that Bart van Ingen Schenau had answered this question to some extent.

+24  A: 

It's the declaration of a function taking an int and a pointer to a function (taking int returning void) and returning a pointer to a function (taking int and 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.

void (*signal(int sig, void (*func)(int)))(int);

The entity in the brackets looks like a function taking int and returning void.

Stripping away the outer part:

*signal(int sig, void (*func)(int))

So, signal takes some parameters and returns something that can be dereferenced (due to the leading *) to form a function taking int and returning void.

This means signal is a function returning a pointer to a function (taking int and returning void).

Looking at the parameters it takes an int (i.e. sig) and void (*func)(int) which is a pointer to a function (taking int and returning void).

Charles Bailey
+1. Very concise. It helps to know the Clockwise/spiral rule when trying to parse complex C declarations. - http://c-faq.com/decl/spiral.anderson.html
Noufal Ibrahim
Personally, I'm not a fan of the clockwise/sprial rule. I prefer to work from the outside in. I know it's not a popular approach, but I'm much happier that I'm applying the grammar rules correctly with my approach.
Charles Bailey
It's funny that the clockwise/spiral rule page linked above includes the very same declaration that the OP is asking about.
Jon Purdy
A: 

returning pointer to a funtion which takes an integer as first argument argument and a pointer to a function (which takes an int and returns void )as an argument as a second argument. and takes an integer argument.

Vijay Sarathi
+3  A: 
Bart van Ingen Schenau