Dik T. Winter:
The following is a bit complicated:
void (*(*f)(int (*)(int)))(int (*)());
cdecl has no problems with it.
Yippie! I'll think out loud, if you don't mind.
Okay, I see "f", so I know that the name of the entire entity is "f".
It has an asterisk directly to its left and both are enclosed within
parentheses, so it must be a pointer.
(Now, in my mind, I'll replace (*f) with simply f.)
Now I'm looking at:
void (*f(int (*)(int)))(int (*)());
I see that f has parentheses containing types directly to its right, so it
must be a function. (I haven't looked at the asterisk to its left yet
because the parentheses have higher precedence). The function has the
following sole parameter:
int (*)(int)
This is a pointer to an int-returning-function whose sole parameter is
an int.
(Now in my mind, I'll replace f(int (*)(int)) with simply f.)
Now, I'm looking at:
void (*f)(int (*)());
I now see that f has an asterisk directly to its left, and both are
enclosed in parentheses, so f must be a pointer.
(Now in my mind, I'll replace (*f) with simply f.)
Now I'm looking at:
void f(int(*)());
This is a void-returning-function whose sole parameter is a pointer to an
int-returning-function whose parameter list is void. (The empty-parentheses
variable-parameter-list rule doesn't apply because we're not dealing with
the declaration of an actual existant function). Therefore, it's equivalent
to:
void f(int(*)(void));
So if I put them all togther, I have:
(1) f is a pointer.
(2) f is a function whose sole parameter is a pointer to an int-returning-
function whose sole parameter is an int.
(3) f is a pointer.
(4) f is a void-returning-function whose sole parameter is a pointer to an
int-returning-function whose parameter list is void.
To simplify the entire thing with typedef's, we work backwards. First of
all though, I want to get rid of those pesky function pointer types:
typedef int (*FuncPtr1)(int);
typedef int (*FuncPtr2)(void);
Now we can work backwards from (4) above:
typedef void T4(FuncPtr2);
typedef T4 *T3;
typedef T3 T2(FuncPtr1);
typedef T2 *T1;
If the compiler doesn't give us a type-mismatch, then we've probably done
it right:
typedef int (*FuncPtr1)(int);
typedef int (*FuncPtr2)(void);
typedef void T4(FuncPtr2);
typedef T4 *T3;
typedef T3 T2(FuncPtr1);
typedef T2 *T1;
int main(void)
{
/* First let's make an object of the original type. */
void (*(*f)(int (*)(int)))(int (*)()) = 0;
/* Now let's make an object of our own type. */
T1 obj = 0;
/* Now let's see if we get a type-mismatch when
we try to assign them. */
f = obj;
obj = f;
return 0;
}
It shouldn't be too hard to work with the type now. I'd post example code,
but I can't think of any contrived usage which wouldn't come across as
utterly facetious (given the obscure nature of the type in question).