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:
signal
takes two parameters. The first parameter ofsignal
is of typeint
and is namedsigno
. The second parameter ofsignal
is of typevoid(*)(int)
and is namedfunc
. That is,func
is a pointer to a function with one parameter of typeint
and return type ofvoid
.signal
has the return typevoid (*)(int)
. That is the return type ofsignal
is a pointer to a function that takes one parameter of typeint
and has return type ofvoid
.
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
.