Home > OS >  how to interpret this c typedef
how to interpret this c typedef

Time:08-01

the origin c declaration is

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

I could understand this statement declare a function call signal that takes an int and an pointer to a function as parameters and returns a pointer to a function. But the use of the typedef as follows is hard to understand:

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

If I replace the "Sigfunc" with "void (int)", I couldn't transform the second declaration to the first. How to interpret the typedef in a right way.

What'more , can I write the following code to get the equivalent declaration

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

CodePudding user response:

Case 1

In the statement:

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

The above is a declaration for a function named signal that has the following properties:

  1. signal takes two parameters. The first parameter of signal is of type int and is named signo. The second parameter of signal is of type void(*)(int) and is named func. That is, func is a pointer to a function with one parameter of type int and return type of void.

  2. signal has the return type void (*)(int). That is the return type of signal is a pointer to a function that takes one parameter of type int and has return type of void.

To make this more readable we can use the placeholder type auto and decltype in C 11(as this question was originally tagged C also) as shown below:

//more readable
auto signal(int signo, void (*func)(int)) -> void(*)(int); 

Case 2

Now lets look at the second case:

typedef void Sigfunc(int); //Sigfunc is a typedef for the function type void (int)
Sigfunc *signal(int signo, Sigfunc *func);

SigFunc is a typedef for the function type void (int). Thus Sigfunc* is nothing but void (*)(int). And since in this case the return type is specified as Sigfunc*, the return type is the same as void (*)(int). Note that specifying the * is important here.


Case 3

Now lets look at case 3:

typedef void (*p_Sigfunc)(int); //p_Sigfunc is a typedef for void (*)(int)
p_Sigfunc   signal(int signo, p_Sigfunc func);
//--------^------------------------------------>no need for explicitly writing "*" here

Here p_Sigfunc is a typedef for void (*)(int). Note in this case we don't need to the * because we already have void (*)(int) instead of void (int).

All of these function declarations are equivalent.

CodePudding user response:

Breaking it down:

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

So two things - the func parameter is a pointer to Sigfunc and signal returns a pointer to Sigfunc.

Since Sigfunc is an alias for "function taking an int parameter and returning void", then Sigfunc * declares a pointer to a function taking an int parameter an returning void. IOW:

Sigfunc  f == void f(int);
Sigfunc *p == void (*p)(int);

Thus,

Sigfunc *signal( int signo, Sigfunc *func ) ==
Sigfunc *signal( int signo, void (*func)(int)) ==
void (*signal( int signo, void (*func)(int) ))(int)

And yes, you can do

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

But...

I am not a fan of hiding pointers (including function pointers) behind typedefs in general. Pointer semantics are special, and unless you are willing to build an API that completely isolates pointer-ness (such that the user of the type doesn't have to be aware of it at all), don't hide them behind a typedef.

CodePudding user response:

Try this approach, to understand this.

typedef void Sigfunc(int);

This type says: a function that takes an int and returns void.

typedef Sigfunc *Sigfunc2;

This type says: a pointer to a Sigfunc. And since Sigfunc is a function that takes an int and returns void then: this is a pointer to a function that takes an int and returns void; which is, again:

typedef void (*Sigfunc2)(int);

This type says the same thing: a pointer to a function that takes an int and returns void.

  • Related