I am trying to really understand function pointers without using typedef
but cannot seem to get this. I do not understand what signature is needed to convey that I return a pointer to a pointer to a function.
#include <stdio.h>
void odd() { printf("odd!\n"); }
void even() { printf("even!\n"); }
void (*get_pfn(int i))()
{
return i % 2 == 0 ? &even : &odd;
}
__SIGNATURE__
{
return &get_pfn;
}
int main()
{
get_pfn_pfn()(1)();
get_pfn_pfn()(2)();
return 0;
}
To make this work, what does __SIGNATURE__
have to be?
Return Function Pointer From Function: To return a function pointer from a function, the return type of function should be a pointer to another function. But the compiler doesn't accept such a return type for a function, so we need to define a type that represents that particular function pointer.
You cannot return a function in C - you return a pointer to a function. If you mean to define a function which returns a pointer to a function which again returns a pointer to a function and so on, then you can use typedef to implement it.
int (*f) (int * ): A pointer to a function that takes an integer pointer as argument and returns an integer.
Function Pointer Syntaxvoid (*foo)( int ); In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It's as if you're declaring a function called "*foo", which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function.
It has to return a function pointer to a function that takes an int
and returns a function pointer:
void (*(*get_pfn_pfn(void))(int))(void) {
return &get_pfn;
}
more lines:
void (*
(*
get_pfn_pfn(void) // this is our function
)(int i) // this is get_pfn(int)
)(void) // this is odd() or even()
{
return &get_pfn;
}
The void
s can be omitted, in which case the function pointer points to a function that takes unknown number of parameters. Which is not what you want. To declare a function pointer to a function that takes no arguments, you should add void
inside function parameter list. The same way it's best to change get_pfn
to void (*get_pfn(int i))(void)
. For example try calling from get_pfn(1)("some arg", "some other arg");
. A C compiler will not give a warning, as empty ()
denote unknown arguments. To say that function takes no arguments, you have to (void)
.
For many the sequences of braces, especially ))(
, in function pointers are hard to parse. That's why many prefer typedefs for function pointers or types:
typedef void get_pfn_func_t(void);
get_pfn_func_t *get_pfn(int i) {
return i % 2 == 0 ? &even : &odd;
}
typedef get_pfn_func_t *get_pfn_pfn_func_t(int i);
get_pfn_pfn_func_t *get_pfn_pfn(void) {
return &get_pfn;
}
Function pointers without a typedef
can be tricky to work with. To figure them out, you work from the inside out.
So let's break down exactly how we come up with the correct function signature.
get_pfn_pfn
is a function:
get_pfn_pfn()
Which takes no parameters:
get_pfn_pfn(void)
And returns a pointer:
*get_pfn_pfn(void)
To a function:
(*get_pfn_pfn(void))()
Which takes an int
parameter:
(*get_pfn_pfn(void))(int)
And returns a pointer:
*(*get_pfn_pfn(void))(int)
To a function:
(*(*get_pfn_pfn(void))(int))()
Which takes no parameters:
(*(*get_pfn_pfn(void))(int))(void)
And returns nothing (i.e. void
):
void (*(*get_pfn_pfn(void))(int))(void)
Of course, using typedef
's simplifies this greatly.
First the type for even
and odd
:
typedef void (*func1)(void);
Which we can then apply to get_pfn
:
func1 get_pfn(int) { ... }
Then the type for this function:
typedef func1 (*func2)(int);
Which we can apply to get_pfn_pfn
:
func2 get_pfn_pfn(void) { ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With