The most important part here is... you don't need to learn this, it is a very poorly designed part of the language. You can scroll down to the bottom of the answer to find the sane, professional solution.
Otherwise, if you insist, it goes like this...
When trying to return a function pointer from a function, the type of the function pointer gets split up. If you want to return a function pointer void(*)(void)
, then this poor function pointer gets split up in 3 parts. Lets call them like this:
void
is A, the return type of the pointed-at function.
(*)
is B, marking this a pointer to function, rather than a function.
(void)
is C, the parameters of the pointed-at function.
Then if we want to stick this as a return type into some other icky function declaration, they end up like this:
#define A void
#define B *
#define C (void)
// A (B) C equals void(*)(void)
A (B madness(int, void (*fp)(int))) C;
where A, B and C are the parts of our poor function pointer to be returned, madness
is the name of the function, and the rest is some mess used as parameters by the function itself.
If we omit the B part, it will be interpreted like a function returning another function of type void f (void);
which isn't valid. The syntax allows it but not the language specification.
Similarly, int foo (void) [3];
- a function returning an array, is not allowed either.
Pondering these things is the road to madness and it makes the code unreadable. Professional programmers use typedef
.
Given
void (*madness(int, void (*f)(int)))(int);
replace it with:
typedef void func_t (int);
func_t* sanity (int, func_t* f);