C signal code explanation needed - c

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);

Related

Meaning of returns char when return value is void, and gets an void argument?

I am learning about threading with C, and I'm a bit confused about the example given. They declared a function print_name with return value of void, but then it returns a string — how and why? The function print_name accepts one argument which is called name but it is a pointer of void; what does a variable of type void mean, and how can it accept a string?
main.c
#include <stdio.h> // I-O
#include <pthread.h> // threading
void *print_name(void *name)
{
puts(name);
return name;
}
int main(int argc, char const *argv[])
{
pthread_t thread_id;
pthread_create(&thread_id, NULL, print_name, "ha ones be eilat");
pthread_join(thread_id, NULL);
return 0;
}
To compile and run with gcc
$ cc main.c -o main -Wall -pthread && ./main
ha ones be eilat
The argument type and return type is not void but pointer to void.
In C both argument passing and returning a value with the return statement happen as if by assignment. void * is a generic pointer type and conversions to and from void * from and to other pointer types will happen implicitly, i.e. without a cast.
The character literal which is an array of char decays to char * and is implicitly converted to void * to match the prototype of pthread_create. The void * is implicitly converted to char * to match the prototype of puts.
print_name has prototype void * print_name(void *) so that a pointer to that function will match the type expected by pthread_create (The third parameter is void *(*start_routine) (void *).)
The declaration of pthread_create is
int pthread_create(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg
);
The type void * is a 'universal pointer' that can point to any object type. (On many, but not all, machines, a void * can also hold a function pointer — however, that's tangential to this question.) In C, any object pointer can be converted to a void * and back to the original type without change. Using void * can be dangerous; it can be extremely useful (and thread creation can show both dangerousness and usefulness).
Contrary to the claim in the question, the function print_name() is defined to return a void * value as well as accept a void * argument. The pthread_create() function expects a (pointer to a) thread function that matches the signature:
void *thread_function(void *);
And that's what is passed to it. Since the function returns a void *, it is legitimate to return the pointer it was passed, though that is actually an unusual thing to do.
The return value from the thread function can be collected by passing an appropriate, non-NULL pointer to pthread_join(); the example does not demonstrate that.
void *result;
if (pthread_join(thread_id, &result) == 0)
printf("Result: <<%s>>\n", result);
This would, in the example, print Result: <<ha ones be eilat>> on a line. Many times, you'd convert the returned pointer to an explicit non-void pointer — e.g. char *str = result; — and then use that.
Note that there is nothing in C that would stop you calling:
int i = 0;
if (pthread_create(&thread_id, NULL, print_name, &i) != 0)
…thread creation failed…
The wrong type of data is passed, but that will be treated as OK by the compiler. At run-time, if you're (un)lucky, an empty line will be printed, but anything is possible (because of undefined behaviour) as you passed an int * to a function that requires a char * to work correctly. This inability to check types is a weakness of void *, but it is also a strength as it allows the pthread_create() function to pass a pointer to any type of data to a function. The onus is on the programmer to get the types right — the called function must expect to convert the void * parameter to a pointer to the type that was really passed. Also, the data passed via the pointer to the function needs to be stable — not changed if another thread is started. There is no guarantee about the order in which threads will read the data passed. Passing a pointer to a structure and changing the value in the structure between calls to pthread_create() is a no-no. Similarly with the return value. There are some additional wrinkles there. The data pointed at must be valid after the function exits, so it can't be a local variable.

Embedded Function Pointers

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.

How to use a function pointer to return a function pointer? [duplicate]

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!

How do I read this complex declaration in C? [duplicate]

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);

How to understand this define

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.

Resources