17

Possible Duplicate:
what's the meaning of this piece of code? void (*signal(int sig, void (*func)(int)))(int);

I have a complex declaration which have been taken from the "signal.h" header file, and below is the declaration.

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

Now, how do I parse it? As

signal is function taking two arguments ‘sig’ of int type and ‘func’, which is a pointer to a function taking int as an argument and returns void type; it returns a pointer to the function taking int as argument and returning void.

Is it OK or signal is a pointer to function?

Community
  • 1
  • 1
Amit Singh Tomar
  • 8,380
  • 27
  • 120
  • 199

5 Answers5

63

Start with the leftmost identifier and work your way out, remembering that [] and () bind before *, so *a[] is an array of pointers, (*a)[] is a pointer to an array, *f() is a function returning a pointer, and (*f)() is a pointer to a function:

       signal                                     -- signal
       signal(                          )         -- is a function
       signal(    sig,                  )         -- with a parameter named sig
       signal(int sig,                  )         --   of type int
       signal(int sig,        func      )         -- and a parameter named func
       signal(int sig,      (*func)     )         --   which is a pointer
       signal(int sig,      (*func)(   ))         --   to a function
       signal(int sig,      (*func)(int))         --     taking an int parameter
       signal(int sig, void (*func)(int))         --     and returning void
      *signal(int sig, void (*func)(int))         -- returning a pointer
     (*signal(int sig, void (*func)(int)))(   )   -- to a function
     (*signal(int sig, void (*func)(int)))(int)   --   taking an int parameter
void (*signal(int sig, void (*func)(int)))(int);  --   and returning void

signal associates a signal handler function func with a signal sig, and returns the pointer to the old signal handler function:

void new_interrupt_handler(int sig)
{
  ... // do something interesting with interrupt signal
}

int main(void)
{
  void (*old_interrupt_handler)(int);
  ...
  /**
   * Set up our new interrupt handler
   */
  old_interrupt_handler = signal(SIGINT, new_interrupt_handler);
  ...
  /**
   * Restore original interrupt handler
   */
  signal(SIGINT, old_interrupt_handler);
  ...
}
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 4
    +1 Very nice, step by step explanation. – watbywbarif Feb 29 '12 at 14:46
  • Thanks @John for your thoughts but some users here opposing it and saying signal is pointer to function . – Amit Singh Tomar Feb 29 '12 at 14:51
  • @Amit - In Aaron's case, the string he fed to `cdecl` is not what you wrote in your question. – John Bode Feb 29 '12 at 15:00
  • 1
    +1 One of the reasons why you use typedef for function pointers: it's easier on the brain. :) – netcoder Feb 29 '12 at 16:33
  • 1
    @netcoder: It can certainly make declarations like this easier to read, but I like knowing what the function signature looks like without having to search for the typedef. `sighandler func;` doesn't tell me how to *use* `func`, whereas `void (*func)(int);` does. – John Bode Feb 29 '12 at 16:42
  • +1 For I wish your answer could be posted to the original question posted above for which this one is a dupe. – Joshua Drake Feb 29 '12 at 19:38
3

Using cdecl.org, you get

declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void

for the input

void (*signal(int, void(*)(int)))(int)

This means signal is a function. The result of of calling signal is pointer to a function void f(int).

Explanation: The signal() call installs a new signal handler and returns the old signal handler (so you can restore it later if you want to).

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
2
void (*signal(int, void (*)(int)))(int);  

       signal(                  )         // signal is a function
              int, void (*)(int)          // the parameter types of the function:
                                          //    an int and a function pointer (take int, return void)
void (*                          )(int);  // the return type of the function:
                                          //    a function pointer (take int, return void)

// Edit referring to John's answer.

Ade YU
  • 2,292
  • 3
  • 18
  • 28
1

signal is a function which takes two parameters and returns a pointer to a function which takes an int as the parameter and returns void.

The two parameters that signal takes are an int and a pointer to a function which takes int as a parameter and returns void.

And yes, you got the description and the overall idea right.

Gangadhar
  • 1,893
  • 9
  • 9
1

No that's right. signal takes 2 arguments, an int and a pointer to a function and returns a pointer to a function (with the same signature as the func argument.)

It's similar to the (imo) more readable:

typedef void (*sig_func)(int);
sig_func signal(int sig, sig_func func);
nos
  • 223,662
  • 58
  • 417
  • 506
  • GNU calls it `sighandler_t`, libc4 and libc5 call it `SignalHandler` and glibc calls it `sig_t`, BTW. ;) – Gandaro Feb 29 '12 at 14:49
  • This is how you should write the code. If you aren't using typedef when declaring something so obscure as "a function pointer to a function taking function pointers as parameter", then you are evil and possibly quite daft. – Lundin Feb 29 '12 at 14:56