How do I interpret complex declarations like:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
The clockwise/spiral:
* http://c-faq.com/decl/spiral.anderson.html
Start with the leftmost identifier and work your way out, remembering that absent any explicit grouping []
and ()
bind before *
, e.g:
*a[] -- is an array of pointer (*a)[] -- is a pointer to an array *f() -- is a function returning pointer (*f)() -- is a pointer to a function
Thus, we read int *(*(*fp1)(int))[10]
as:
fp1 -- fp1
*fp1 -- is a pointer
(*fp1)(int) -- to a function
taking an int parameter
*(*fp1)(int) -- returning a pointer
(*(*fp1)(int))[10] -- to a 10-element array
*(*(*fp1)(int))[10] -- of pointer
int *(*(*fp1)(int))[10] -- to int
The declaration int *(*(*[5])())()
presents a bit of a challenge since there's no identifier; you typically see this in function declarations where a parameter is of that type:
void foo(int *(*(*[5])())(), double);
It's the same principle as the unnamed int
parameter in the declaration of fp1
. The array gives us the clue, you can also look for the leftmost inner grouping of parentheses.
-- unnamed
[5] -- is a 5-element array ([] binds before *)
*[5] -- of pointers
(*[5])() -- to functions
*(*[5])() -- returning pointers
(*(*[5])())() -- to functions
*(*(*[5])())() -- returning pointers
int *(*(*[5])())() -- to int
Though it's has been answered already, but you may also read this article :
http://unixwiz.net/techtips/reading-cdecl.html
I've learned the following method long ago:
Start from the type identifier (or the inner parenthesis) and move following a spiral taking the element at right first
In case of
int * (* (*fp1) (int) ) [10];
You can say:
Resulting in:
fp1 is a pointer to a function taking an int and returning a pointer to an array of 10 pointers to int
Drawing the actual spiral (in you your mind, at least) helps a lot.
No, you don't need to read it loud with complex steps like "clockwise/spiral rule" and "the right rule". Why should you? You only need to know how to use it! Don't make the simple one complex.
C declarations in fact work in a simple rule: declare as how would be used.
Consider the code you gives out:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
For the first declaration, this means that *(*(*fp1)(int))[int]
is an int
. And that's it.
For example, you know that *(*(*fp1)(5))[0]
is an int, and *(*(*fp1)(2))[9]
is an int too.
And The second declaration is incomplete. Even gcc won't know what you want to convey.
Here is a great article about how to read complex declarations in C: http://www.codeproject.com/KB/cpp/complex_declarations.aspx
It helped me a lot!
Especially - You should read "The right rule" section. Here quote:
int * (* (*fp1) (int) ) [10]; This can be interpreted as follows:
- Start from the variable name -------------------------- fp1
- Nothing to right but ) so go left to find * -------------- is a pointer
- Jump out of parentheses and encounter (int) --------- to a function that takes an int as argument
- Go left, find * ---------------------------------------- and returns a pointer
- Jump put of parentheses, go right and hit [10] -------- to an array of 10
- Go left find * ----------------------------------------- pointers to
- Go left again, find int -------------------------------- ints.