Help me understand the following prototype. What is the last (int) doing?
void ( *signal(int sig, void (*handler)(int)) ) (int);
Find the leftmost identifier and work your way out, remembering that [] and () bind before *; IOW, *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. Thus,
void ( *signal(int sig, void (*handler)(int)) ) (int);
breaks down as
signal -- signal
signal( ) -- is a function
signal( sig ) -- with a parameter named sig
signal(int sig, ) -- of type int
signal(int sig, handler ) -- and a parameter named handler
signal(int sig, *handler ) -- which is a pointer
signal(int sig, (*handler)( )) ) -- to a function
signal(int sig, (*handler)(int)) ) -- taking an int parameter
signal(int sig, void (*handler)(int)) ) -- and returning void
*signal(int sig, void (*handler)(int)) ) -- returning a pointer
( *signal(int sig, void (*handler)(int)) )( ) -- to a function
( *signal(int sig, void (*handler)(int)) )(int) -- taking an int parameter
void ( *signal(int sig, void (*handler)(int)) )(int); -- and returning void
The signal function associates a signal (sig) with a callback function (handler), like so:
#include <signal.h>
static int interrupt = 0;
/**
* The following function will be called when a SIGINT is
* detected (such as when someone types Ctrl-C)
*/
void interrupt_handler( int sig )
{
interrupt = 1;
}
int main( void )
{
/**
* Declare a pointer to the old interrupt handler function
*/
void (*old_interrupt_handler )(int);
/**
* Save the old interrupt handler while setting the new one
*/
old_interrupt_handler = signal( SIGINT, interrupt_handler );
while ( !interrupt )
{
// do stuff until someone hits Ctrl-C
};
/**
* restore the original interrupt handler
*/
signal( SIGINT, old_interrupt_handler );
return 0;
}
The whole thing declares a function called signal:
signal takes an int and a function pointer
this function pointer takes an int and returns void
signal returns a function pointer
this function pointer takes an int and returns a void
That's where the last int comes in.
You can use the spiral rule to make sense of such declarations, or the program cdecl(1).
As I pointed out in an answer to another recent question, one way to understand these declarations is to swap parameter lists and array declarators with the thing to their left and then read the declaration backwards. In this case that gives you
void ( *signal(int sig, void (*handler)(int)) ) (int)
->
void (int)( *(int sig, void (int)(*handler))signal )
Which reads as "`signal is a function that takes two parameters and returns a pointer to a function that takes an int parameter and returns void". The two parameters are an int (sig) and a pointer (handler) to a function that takes an int parameter and returns void.
Or you can do the swapping mentally, which is the same as the spiral rule.
The above prototype can be written as::
typedef void (*sig_t) (int);
sig_t signal(int sig, sig_t handler);
Now, I hope it would be clear to you.
void (*handler)(int); handler is pointer to a function (say Fn1) with return type voidand takes an int
void (*signal(int sig, Fn1)) (int);
(*signal(int sig, Fn1); This function has return type void and takes an int and function pointer as arguments.
The return type of this function, whose pointer is signal is possibly a function pointer for a function that takes an int[final int] with return type void
it is a function returning a pointer to a function returning void..Source:" Unscrambling C Declarations " in DEEP C SECRETS
Related
We came across this snippet of code in our textbook that was lacking explanation
except the fact that it handles signals.
#include <signal.h>
void (*signal(int signr,
void(*sighandler)(int)
)
)(int)
I know that sighandler is a pointer to a function, but I do not understand if it is actually executed or just returned?
and what does the call with (int) do?
It looks almost like a reversed cast.
This is the signature of the signal function.
The first argument signr is of type int and is the signal whose handler you want to change.
The second argument sighandler is a function pointer of type void (*)(int), i.e. a function that takes an int and returns void. This parameter is the name of a function which will handle the signal.
The function returns a function pointer of type void (*)(int) (same type as argument 2) which points to the previous signal handling function.
Breaking it down:
signal // signal
signal() // is a function
signal(int) // taking a int
signal(int, void (*)(int)) // and a function pointer
// which takes an int and return void
(*signal)(int, void (*)(int))(int) // and returns a function pointer
// which takes an int
void (*signal)(int, void (*)(int))(int) // and returns void
The man page includes a typedef which makes this a bit more clear:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
I'm having trouble understanding this specific declaration:
void (*signal(int, void (*fp)(int)))(int);
My previous understanding of function pointers was that the first item in brackets was the name of the function pointer.
eg
int (*MySuperDuperNameForASimpleAddFunction)(int, int);
I don't understand how it's possible to have anything other than identifiers in the first bracket.
void (*signal(int, void (*fp)(int)))(int);
signal is a function, taking :
an int
a function pointer taking an int and returning void
...and returning a function pointer taking an int and returning void. Phew.
Standard rule: find the leftmost identifier, then work your way out remembering that function-call () 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. Apply this rule recursively for any function parameters.
With all that in mind, the declaration breaks down like so:
signal -- signal
signal( ) -- is a function taking
signal(int, ) -- an int parameter and
signal(int, fp ) -- a parameter named fp of type
signal(int, (*fp) ) -- pointer to
signal(int, (*fp)( )) -- function taking
signal(int, (*fp)(int)) -- an int parameter
signal(int, void (*fp)(int)) -- returning void
(*signal(int, void (*fp)(int))) -- returning a pointer to
(*signal(int, void (*fp)(int)))( ) -- a function taking
(*signal(int, void (*fp)(int)))(int) -- an int parameter
void (*signal(int, void (*fp)(int)))(int); -- returning void
So, signal takes two arguments, one of which is a pointer to a function taking an int and returning void, and returns a pointer to a function of the same type as fp.
The following was accepted by gcc:
static void (*signal(int, void (*fp)(int)))(int) ;
typedef void (sigfunc)(int) ;
static sigfunc* signal(int i, sigfunc* fp)
{
fp(i) ;
return fp ;
} ;
I have no idea why the return value from the signal function has to be wrapped around its definition in this way... and I suspect life is too short to allow me to discover !
I tried static void (*fp)(int) signal(int, void (*fp)(int)) but the computer said NO.
This question already has answers here:
What's the meaning of this piece of code? void (*signal(int sig, void (*func)(int)))(int);
(5 answers)
Closed 9 years ago.
I was studying signal handling in unix and came across this
void (*signal(int sig, void (*func)(int)))(int);
I dont understand this prototype and how this returns a pointer to a function.
I also read this answer:
How do function pointers in C work? but it's not clear to me.
It's supposed to return a function pointer but I dont understand where it specifies the return type as another function pointer.
The way I see it is that, if I use (*foo(int n)) in a function definition the return type of this function foo(int n) becomes a function pointer.Is this correct?
Is there a simpler example for this?
So, let's look at how a function pointer is declared.
return-type (*function-name)(parameter-list);
In the declaration you posted, there are two function-pointer types in play. The first is a parameter that's passed into a function that matches the signal prototype:
void (*signal(int sig, void (*func)(int)))(int);
// ^^^^^^^^^^^^^^^^^
Let's rename that function pointer type to handler and give it its own declaration.
typedef void (*handler)(int);
void (*signal(int sig, handler func))(int);
Now we can break down the rest of the declaration. The "inside" part is the actual function declaration:
...signal(int sig, handler func)...
And the "outside" describes the function pointer it returns:
void (...)(int);
This is also the same function-pointer type as our handler type, so with that typedef in place, we could redeclare the signal function like this:
handler signal(int sig, handler func);
(Much prettier.)
void (*signal(stuff))(int)
declares signal as returning a pointer to a function that takes an int as an argument and returns void. The stuff gives the arguments to signal, which in this case are
(int sig, void (*func)(int))
That is, the first argument to the function signal is an int, and the second argument is a function pointer taking an int as an argument and returning void.
Edit: Thus, if you made some call -- for example,
void foo (int x) {
return;
}
void *bar = (*signal)(0, &foo);
then bar will be a pointer to a function taking an int and returning nothing, and as such can be called as follows:
(*bar)(0);
We can use typedef to simplify the function pointer definition, which can help you to understand the long and complicated definition.
#include <stdio.h>
typedef void (*func)(int);
typedef void (*rtype)(int);
void myfunc(int a)
{
printf("A is %d\n", a);
}
// thus signal can be defined as this
// exactly the same as in your question
rtype signal(int a, func handler)
{
return myfunc;
}
int main()
{
signal(0, 0)(12);
return 0;
}
the above code should output: A is 12;
Hope helps!
This question already has answers here:
Closed 10 years ago.
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?
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);
...
}
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).
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.
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.
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);
Nowadays , i was reading the APUE.and i found the function defined as below:
void (*signal(int signo, void (*func)(int)))(int);
i was confused, i know signal is pointer to a function and the last (int) is his parameter.
i did not know what is (int signo,void (*func)(int)).
The general procedure: find the leftmost identifier and work your way out. Absent an explicit grouping with parentheses, postfix operators such as () and [] bind before unary operators like *; thus, the following are all true:
T *x[N] -- x is an N-element array of pointer to T
T (*x)[N] -- x is a pointer to an N-element array of T
T *f() -- f is a function returning a pointer to T
T (*f)() -- f is a pointer to a function returning T
Applying these rules to the declaration, it breaks down as
signal -- signal
signal( ) -- is a function
signal( signo, ) -- with a parameter named signo
signal(int signo, ) -- of type int
signal(int signo, func ) -- and a parameter named func
signal(int signo, *func ) -- of type pointer
signal(int signo, (*func)( )) -- to a function
signal(int signo, (*func)(int)) -- taking an int parameter
signal(int signo, void (*func)(int)) -- and returning void
*signal(int signo, void (*func)(int)) -- returning a pointer
(*signal(int signo, void (*func)(int)))( ) -- to a function
(*signal(int signo, void (*func)(int)))(int) -- taking an int parameter
void (*signal(int signo, void (*func)(int)))(int); -- and returning void
In short, signal returns a pointer to a function returning void. signal takes two parameters: an integer and a pointer to another function returning void.
You could use typedefs to make this easier to read (and the man page for signal on Ubuntu linux does just that); however, I think it's valuable to show the non-typedef'd version to demonstrate exactly how the syntax works. The typedef facility is wonderful, but you really need to understand how the underlying types work in order to use it effectively.
The signal function sets up a signal handler; the second argument is the function that is to be executed if a signal is received. A pointer to the current signal handler (if any) is returned.
For example, if you want your program to handle interrupt signals (such as from Ctrl-C):
static int g_interruptFlag = 0;
void interruptHandler(int sig)
{
g_interruptFlag = 1;
}
int main(void)
{
...
/**
* Install the interrupt handler, saving the previous interrupt handler
*/
void (*oldInterruptHandler)(int) = signal(SIGINT, interruptHandler);
while (!g_interruptFlag)
{
// do something interesting until someone hits Ctrl-C
}
/**
* Restore the previous interrupt handler (not necessary for this particular
* example, but there may be cases where you want to swap out signal handlers
* after handling a specific condition)
*/
signal(SIGINT, oldInterruptHandler);
return 0;
}
EDIT I extended the example code for signal to something that's hopefully more illustrative.
void (*signal(int signo, void (*func)(int)))(int);
signal is function that takes int and a pointer to function taking int and returning void and returns a function pointer taking int and returning void. That is,
typedef void(*funcPtr)(int)
then we have
funcPtr signal(int signo, funcPtr func); //equivalent to the above
The syntax is indeed strange, and such things better be done with a typedef. As an example, if you want to declare a function that takes an int and returns a pointer to a function taking char and returning double will be
double (*f(int))(char);
Edit: after a comment that reads "Wooooooow", I am providing another example which is more "woooow" :)
Let's declare a function that takes
1. a pointer to array of 5 pointers to functions each taking float and returning double.
2. a pointer to array of 3 ponters to arrays of 4 ints
and returns a pointer to function that takes a pointer to function taking int and returning a pointer to function taking float and returning void and returns unsigned int.
The typedef solution would be this:
typedef double (*f1ptr) (float);
typedef f1ptr (*arr1ptr)[5];
typedef int (*arr2ptr)[4];
typedef arr2ptr (*arr3ptr)[3];
typedef void(*f2Ptr)(float);
typedef f2ptr (*f3ptr)(int);
typedef unsigned int (*f4ptr) (f3ptr);
f4ptr TheFunction(arr1ptr arg1, arr3ptr arg2);
Now, the funny part :) Without typedefs this will be:
unsigned int (*TheFunction( double (*(*)[5])(float), int(*(*)[3])[4]))( void(*(*)(int))(float))
My god, did I just write that? :)
The Clockwise Spiral rule will help:
http://c-faq.com/decl/spiral.anderson.html
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
[X] or [] => Array X size of... or Array undefined size of...
(type1, type2) => function passing type1 and type2 returning...
=> pointer(s) to...
Keep doing this in a spiral/clockwise direction until all tokens have been covered.
Always resolve anything in parenthesis first!
See "Example #3: The 'Ultimate'", which is pretty much exactly what you are asking for:
"signal is a function passing an int and a pointer to a function passing an int returning nothing (void) returning a pointer to a function passing an int returning nothing (void)"
In case you don't have access to cdecl right now, here is the cdecl output:
$ cdecl
cdecl> explain void (*signal(int , void (*)(int)))(int);
declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void
This site gives declerations to C gibberish:
C gibberish <-> English
Install cdecl for your distribution (if available) or go here
Otherwise, I believe Armen Tsirunyan's answer is correct.