1

While working with very old minix sw (MINIX 1.5) I encountered weird function declarations; 1) the declaration of a function's prototype, and 2) the declaration of the function itself

/* in header file the prototype of a signal function, with my annotations */

     /*---is this some sort of casting ???---*/
             /*----two input arguments----*/
void (*signal(int sig,  void (*_func)(int) )  )  (int);

                        /*---func ptr---*/

I can only deduct a casting, but what is casted here and how would you describe the resulting function? The same definition is maintained in the code file, so we are definitely talking a function declaration, but its output is not clear to me. Refer to the next code snippet. Some reference to documentation is welcome.

/* in the code file */

PUBLIC void (*signal(int signr, void (*func)(int))) (int){
  void (*old) (int);

  /* there is more code, but not relevant for the problem */

return(old);
}



OldProgrammer
  • 12,050
  • 4
  • 24
  • 45
BenJ
  • 23
  • 5
  • cdecl: "declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void" – 001 May 08 '23 at 12:50
  • There is no casting involved here. You have a function that takes a function pointer and also returns a function pointer. – Gerhardh May 08 '23 at 12:50

3 Answers3

2

Normally I would not advice to hide a pointer type in a typedef. This might be one of the exceptions.

You can make your life easier:

typedef void (*sig_func_type)(int);

sig_func_type signal(int sig, sig_func_type func);
Gerhardh
  • 11,688
  • 4
  • 17
  • 39
2

There's no cast here. What you have is a function that takes a function pointer as one of its arguments and returns a function pointer.

Linux uses a similar declaration, but the man page shows it using typedefs for the function pointers to make it more clear:

   typedef void (*sighandler_t)(int);

   sighandler_t signal(int signum, sighandler_t handler);
dbush
  • 205,898
  • 23
  • 218
  • 273
2

In void (*signal(int sig, void (*_func)(int) ) ) (int);, matching the first open parentheses with its close parentheses shows the form is void (…)(int);.

This declares a function with an int parameter and returning nothing (void).

Inside the parentheses, we have *signal(int sig, void (*_func)(int) ). Again matching the first open parentheses to its close parentheses gives the form *signal(), so we see this is a function returning a pointer to the surrounding type, which we know from above is a function with an int parameter returning void.

Therefore signal is a function that returns a pointer to a function with an int parameter returning void.

Looking inside the parentheses after signal, we know these are the parameters to the function signal, and they are int sig and void (*_func)(int).

int sig clearly declares an int parameter. void (*_func)(int) declares (*_func) to be a function taking an int parameter and returning void. Since (*_func) is a function, _func is a pointer to a function.

So the entire declaration declares signal to be a function that takes a first parameter that is an int and a second parameter that is a pointer to a function taking an int parameter and returning void, and signal returns a pointer to a function taking an int parameter and returning void.

If you call a function that takes an int parameter and returns void a “signal handler,” then signal is a function that takes an int and a pointer to a signal handler and that returns a pointer to a signal handler.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312