Professional Documents
Culture Documents
const charp p;
Why is p turning out const, instead of the characters pointed to?
typedef substitutions are not purely textual. (This is one of the advantages of
typedefs; see question 1.13.) In the declaration
const charp p;
p is const for the same reason that const int i declares i as const. The typedef
'ed declaration of p does not ``look inside'' the typedef to see that there is a
pointer involved.
################################################
######
The first part of this question can be answered in at least three ways:
1. char *(*(*a[N])())();
2. Build the declaration up incrementally, using typedefs:
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... */
3. Use the cdecl program, which turns English into C and vice versa. You prov
ide a longhand description of the type you want, and cdecl responds with the equ
ivalent C declaration:
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, a
nd a declarator which contains the identifier or name being declared, perhaps al
ong 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 exampl
e, in
char *pc;
the base type is char, the identifier is pc, and the declarator is *pc; this tel
ls 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 poin
ter (the outer *) to char. When we later use pfpc, the expression *(*pfpc)() (th
e 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'' relations
hip:
*(*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 par
ameter type information. When the parameters have complicated types, declaration
s can really get messy. (Modern versions of cdecl can help here, too.)
Additional links:
A message of mine explaining the difference between array-of-pointer vs. pointer
-to-array declarations