You are on page 1of 3

typedef char *charp;

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.

[This is] another of the differences between typedef and #define.


Type qualifiers like const can affect a pointer variable in two (or more) differ
ent ways: either the pointer can be qualified, or the value pointed to. As quest
ion 11.9 in the C FAQ list explains, when you write
int * const p;
the pointer p is qualified, but when you write
const int * p;
the value pointed to is qualified.
Now, if you say
#define x int*
and then
const x y;
the result is exactly as if you had written
const int* y;
so it is the pointed-to value that is qualified. The preprocessor always does si
mple textual substitutions, and these take place before the compiler performs it
s parsing phase.
When you say
typedef int * x;
on the other hand, x is a new type, encapsulating the notion pointer to int . Now,
when you say
const x y;
it is the variable y that is qualified, just as if you'd said
const int y;

################################################
######

How do I construct declarations of complicated types such as ``array of N pointe


rs to functions returning pointers to functions returning pointers to char'', or
figure out what similarly complicated declarations mean?

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

You might also like