confused about syntax in void function

I'm fairly new to c++ and I'm confused about syntax in a void declaration from the cplusplus reference.
It's an example of the signal.h libraries.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* signal example */
#include <stdio.h>      /* printf */
#include <signal.h>     /* signal, raise, sig_atomic_t */

sig_atomic_t signaled = 0;

void my_handler (int param)
{
  signaled = 1;
}

int main ()
{
  void (*prev_handler)(int);

  prev_handler = signal (SIGINT, my_handler);

  /* ... */
  raise(SIGINT);
  /* ... */
  
  printf ("signaled is %d.\n",signaled);
  

  return 0;
}


What is that void declaration? It doesn't appear to be a function or a variable. I figure it must be some odd method of calling prev_handler as a int casted void pointer however, I would think that if that was the case I could declare it like this and get the same result

 
void (int) *prev_handler
Kinda new myself, but this is what I can gather.

void (*prev_handler) (int); is what you have.
void (int) *prev_handler; does not work, stating that a type is not allowed (where int is).
void *prev_handler; is a valid statement, and in fact, it works fine.

What (int) is doing after is explicitly casting as int (I think). The parentheses need to include both the * symblol and the word prev_handler, or else you get an error saying that prev_handler must be a modifiable value.

void is a special type for pointers, which I found here: http://www.learncpp.com/cpp-tutorial/613-void-pointers/

The reason why we have it in this particular format is SIMPLY because that is the format of signal (SIGINT, my_handler);

If you hover your cursor over where it says "signal" in the code on the function call, then you will see its own format, which is basically a void pointer to a thing cast as an int. Hope I was helpful.
Last edited on
Line 14 is a function pointer. In this case, the signature of the function pointed to returns nothing (void) and accepts a single int.

Line 16 registers my_handler as the function to be called when a SIGINT occurs. signal returns a function pointer to the previous signal handler for SIGINT (if any). That function pointer is save in prev_handler.

nickeeromo wrote:
What (int) is doing after is explicitly casting as int

No. Signal handlers accept one int as a param as in my_handler. No casting is involved.

nickeeromo wrote:
void is a special type for pointers

Again no. A void typed function indicates the function does not return anything. This is completely different from void pointers.

nickeeromo wrote:
you will see its own format, which is basically a void pointer to a thing cast as an int.

You need to learn about function pointers. You're confusing a pointer to a function that returns nothing with a void pointer. They are not the same thing.



Thank you AbstractionAnon for clearing that up for me. And before this discussion, nope - I had never heard of void pointers or function pointers. Just tried to give it a shot based on what I already knew.
Hey, thanks for the response. I'm still a bit confused though.

here is what I understand

The void declaration is a function pointer named prev_handler which accepts an int and returns nothing.

I understand the arguments of the signal function, and it obviously outputs something to prev_handler, but what then?

It seems that the void function encapsulates the signal function, am I correct? why is it done this way?
why isn't signal a void function instead?
I guess you were looking at: http://www.cplusplus.com/reference/csignal/signal/
I understand the arguments of the signal function, and it obviously outputs something to prev_handler, but ...

That "something" is the old value. You can restore the earlier handler with it.

1
2
3
4
5
// Signal SIGINT would call function foo
prev_handler = signal( SIGINT, my_handler );
// Signal SIGINT would call function my_handler
signal( SIGINT, prev_handler ); // we discard the returned value
// Signal SIGINT would again call function foo 


why isn't signal a void function instead?

Convenience. If you indeed want to use your own handler only temporarily, then you will restore the previous handler at some point. In order to restore, you need to know the previous. If signal() would not return it, you would have to have an another library function that simply returns us the "current handler".
To add to what keskiverto said:

It seems that the void function encapsulates the signal function

That's not encapsulation. You're telling the signal handler what function to call when a SIGINT occurs.

The runtime keeps an array of function pointers, one entry for each type of signal that can occur. When you call signal, you're passing a function pointer to your handler for a particular signal (SIGINT). signal simply stores your function pointer in the array entry designated by the index SIGINT and returns the previous function pointer in case you want to restore the previous handler for that particular signal.

When a particular signal occurs, the runtime simply calls the function pointer for the signal number using the n'th entry in the array where n is the signal number. When you restore a previous signal handler, you're simply replacing that entry in the array of function pointers.

By definition, all signal handlers are void functions that accept one int.
Thanks for all of your explanations. I think it is making a little more sense. I did some research and found this tutorial. I thought it was pretty helpful.

http://www.cprogramming.com/tutorial/function-pointers.html
Topic archived. No new replies allowed.