John Humphreys
John Humphreys

Reputation: 39224

Casting integer to function pointer in signal code - why does this work?

I'm reading a book (Advanced Programming in the UNIX Environment) and I'm going through the section on signals.

When using the signal function:

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

the parameter, func, can be a pointer to a function defined by the user, or it can be SIG_ERR, SIG_DFL, or SIG_IGN.

My question isn't on the UNIX part of this, but I wanted to give background. What I really want to know is, the book states that these constants are defiend as:

#define SIG_ERR (void (*)())-1

and the like for 0, and 1.

Now, I have some decent guesses but to save time - can someone tell me what the heck this is doing and why it works?

Also, is there a... erm... cleaner? way to write this assuming I'm using C++ and interacting with this C API?

Upvotes: 10

Views: 616

Answers (3)

user405725
user405725

Reputation:

Well, it does define SIG_ERR as a pointer to void function accepting any number of arguments with address of -1. SIG_DFL has address 0 and SIG_IGN has address of 1. Those are just special values for the original signal processing function, and those addresses are probably implementation details you should not care about. Just use macros kindly defined for you and you will be good.

If you want it cleaner - declare your own functions, for example function that does nothing and ignores signal, and use a pointer to it instead of SIG_IGN...

But I doubt any value in wrapping signal handling in C++ code. For some reason C++ programmers like to wrap absolutely everything, even this simple and straight forward C API.

Upvotes: 2

Kevin
Kevin

Reputation: 56049

#define SIG_ERR (void (*)())-1

This casts -1 to a pointer to a function (namely a function that takes nothing and returns nothing). This will make the SIG_ERR always be invalid and distinct from NULL.

Upvotes: 2

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272447

It's casting an integer to a function pointer;* the placeholder values are presumably chosen so that they could never collide with the values of real function pointers. The implementation of signal presumably then checks the input argument for these special values.


* The C standard allows this (see 6.3.2.3 p.5), although it says that the results are implementation-defined. Obviously, the authors of the OS are able to control the implementation-defined aspects of this, so everything's ok.

Upvotes: 11

Related Questions