Q: How do I construct declarations of complicated types such as ``array of N pointers to functions returning pointers to functions returning pointers to char'', or figure out what similarly complicated declarations mean?
A: The first part of this question can be answered in at least three ways:
typedef char *pc; /* pointer to char */ typedef pc fpc(); /* function returning pointer to char */ typedef fpc *pfpc; /* pointer to above */ typedef pfpc fpfpc(); /* function returning... */ typedef fpfpc *pfpfpc; /* pointer to... */ pfpfpc a[N]; /* array of... */
cdecl> declare a as array of pointer to function returning pointer to function returning pointer to char char *(*(*a)())()cdecl can also explain complicated declarations (you give it a complicated declaration and it responds with an English description), help with casts, and indicate which set of parentheses the parameters go in (for complicated function definitions, like the one above). See question 18.1.
C's declarations can be confusing because they come in two parts: a base type, and a declarator which contains the identifier or name being declared, perhaps along with *'s and 's and ()'s saying whether the name is a pointer to, array of, or function returning the base type, or some combination.[footnote] For example, in
char *pc;the base type is char, the identifier is pc, and the declarator is *pc; this tells us that *pc is a char (this is what ``declaration mimics use'' means).
One way to make sense of complicated C declarations is by reading them ``inside out,'' remembering that  and () bind more tightly than *. For example, given
char *(*pfpc)();we can see that pfpc is a pointer (the inner *) to a function (the ()) to a pointer (the outer *) to char. When we later use pfpc, the expression *(*pfpc)() (the value pointed to by the return value of a function pointed to by pfpc) will be a char.
Another way of analyzing these declarations is to decompose the
declarator while composing the description, maintaining the
``declaration mimics use'' relationship:
*(*pfpc)() is a char (*pfpc)() is a pointer to char (*pfpc) is a function returning pointer to char pfpc is a pointer to function returning pointer to char
If you'd like to make things clearer when declaring complicated types like these, you can make the analysis explicit by using a chain of typedefs as in option 2 above.
The pointer-to-function declarations in the examples above have not included parameter type information. When the parameters have complicated types, declarations can really get messy. (Modern versions of cdecl can help here, too.)
A message of mine explaining the difference between array-of-pointer vs. pointer-to-array declarations
David Anderson's ``Clockwise/Spiral Rule''
K&R2 Sec. 5.12 p. 122
ISO Sec. 6.5ff (esp. Sec. 6.5.4)
H&S Sec. 4.5 pp. 85-92, Sec. 5.10.1 pp. 149-50