It has been said that declarations of variables, types, and functions in C are "inside-out". This is said rightfully so, as you will see. Let us take a very simple variable declaration: int a. a here is obviously an int. This seems pretty straight-forward. Consider a slightly more complex example: int (*a). a is not an int; it is a pointer. The most immediate facet of a is stated immediately next to it.

Let us take next a rather complex example: int (*foo)(double). What is foo? It is a pointer (the second *). A pointer to what? It is a pointer to a function that takes a double for its only argument. What does that function return? It returns an int. So, we say that "foo is a pointer to a function (double) that returns an int". Here's how the cdecl tool explains this to us:
cdecl> explain int (*foo)(double)
declare foo as pointer to function (double) returning int
As you can see, we interpreted it correctly.

Here's a little "trick": When casting to that same type, you simply remove the "foo" part, and put the whole thing in parentheses: (int (*(*)(double)))my_void_ptr, where my_void_ptr is probably of type void *. And, since function prototypes take nameless arguments, you can do the same thing as a cast, without no enclosing parentheses.

Anyway, to add to the confusion, we have little shortcut precedences. These are what let you get away with int *foo instead of int (*foo). They also allow for slightly confusing types: int *bar[]. Is that an array of pointers, or a pointer to an array? Well, the designers of C decided that array should be "more important" than pointers, so it is the same type as int (*(bar[])). Enter both into cdecl, and you will get the same explanation.

Now, try to explain this one: int (*quux[])(char *(*)(double),int *). Hint: quux is the variable's name. And no, I can't think of a practical use for this type.

Log in or register to write something here or to contact authors.