So while I'm waiting for a new virtual image to finish extracting so that I can recover from the disaster that was Friday afternoon, I thought I'd write up a brief introduction to C declarators.
Declarations in C can be confusing to someone not familiar with the language.  Declarations like
int x;float y;are fairly straightforward (x is an integer, y is a single-precision real number), but then you come across something like this:
int *(*(*foo)[10])(int (*bar)[20]);What does that even mean?  How do you read declarations like that?
C follows the paradigm of 
declaration mimics use: in other words, the declaration of an object must look as much like how it will be used in the code that follows.  This is probably best explained with a few examples.
Suppose we have a pointer to an integer, and we want to refer to the pointed-to integer value.  To do this, we would use the dereference operator, '*':
*x = 5;
printf("%d\n", *x);The type of the expression 
*x is int, so our declaration looks like this:
int *x;The keyword 
int is the 
type specifier.  It provides the basic type information for item being declared.  The expression 
*x is called the 
declarator.  It introduces the name of the thing being declared, as well as additional type information.  In the pointer example above, 
x is the name of the variable, and its type is "pointer to int".  However, the "pointerness" of 
x is given by the presence of the 
* operator in the declarator.
Let's look at a more complicated example.  Suppose we have an array of pointers to int, and we want to refer to the integer value pointed to by element 
i of the array.  We would write
x = *arr[i];The declaration for the array 
arr would look like the following:
 int *arr[N];where 
N is a constant integer expression for the size of the array (I'm not familiar enough with C99's variable-sized arrays to provide a usable example).  The type of 
arr is "N-element array of pointers to int."  Again, the "int-ness" of arr is given by the type specifier 
int, but the "array-ness" and "pointer-ness" are given by the declarator 
*arr[N].
Note that the 
* and 
[] operators are bound to the identifier, not the type specifier.  Whitespace makes no difference; in other words, the statements
int* x;and
int *x;are identical.  This also means that the statement
int* x, y;only declares 
x as a pointer; 
y is declared as a regular integer.
So what about the declaration
int *(*(*foo)[10])(int (*bar)[20]);How do you read something like that?  The trick is to find the leftmost identifier and work your way out, remembering that 
() and 
[] bind before 
* (IOW, 
*a[] is an array of pointer, 
(*a)[] is a pointer to an array, 
*f() is a function returning a pointer, and 
(*f)() is a pointer to a function).  So in this case, 
foo                                -- foo
*foo                               -- is a pointer
(*foo)[10]                         -- to a 10-element array
*(*foo)[10]                        -- of pointers
(*(*foo)[10])()                    -- to functions
(*(*foo)[10])(int (*bar)[20])      -- taking a pointer to a 20-element array of int
*(*(*foo)[10])(int (*bar)[20])     -- returning pointer
int *(*(*foo)[10])(int (*bar)[20]) -- to int
Labels: C, coding