in C what is the meaning of this declaration: int *(*table())[30]; - c

int *(*table())[30];
I cannot find a solution anywhere.
What is the *table(), can it be a function or array?
Can you please tell me what that means?

You can decode this from the inside out:
int *(*table())[30];
The innermost binding istable(), which is a function with unspecified arguments. The next level is *table(), so table is returning a pointer to something. The next level is (*table())[30], so it's returning a pointer to a 30-length array of something. The next level is *(table())[30], so it's returning a pointer to a 30-length array of pointers to something. The final level adds the type specifier, int *(*table())[30].
So table is a function (with unspecified arguments) that returns a pointer to a 30-length array of pointers to int.

Reading of such constructs is much easier if you replace parts of the declaration that can be replaced, with a substitute name. Let's say f is table(), which is a function taking unspecified number of arguments, and t is the type int*.
Then the declaration becomes:
t(*f)[30];
which is obviously a pointer to an array of 30 elements of t.
Replace f, and we get a function taking unspecified number of arguments, and returning a pointer to an array of 30 elements of t:
t(*table())[30];
Replace t and we get a function taking unspecified number of arguments, and returning a pointer to an array of 30 elements of pointer to int:
int*(*table())[30];

The line:
int *(*table())[30];
declares that "table is a function returning a pointer to an array of 30 pointers to int."
There are myriad good articles on how to read C type declarations. Here is one of them.
To summarize:
The rules:
There is a type name on the left. Call that $typename.
There is an identifier somewhere towards the right, possibly surrounded by [] and () and *. Call that $identifier.
Your declaration will be templated like: $identifier is a ... $typename.
Start with "$identifier is a(n)".
If you can go right, by consuming a [...] or a (...), then add that to your declaration. The [...] is a (possibly-empty) array declaration, written "array (of ...)"; while the (...) is a (possibly-empty) function declaration, written "function returning" or "function taking (...) returning".
If you cannot go right, because you reach a semicolon, or comma, or a closing parenthesis, then you must go left. Go left, consuming either the $typename if you are at the end of the process, or consuming a pointer declaration (*, written "pointer(s) to") or consuming an opening parenthesis. After consuming any of these, except the $typename, try to go right again.
Remember: Go right if you can, go left if you must.
Your question, revisited
With that in mind, let's look again:
int *(*table())[30];
Step by step:
$typename = "int"
$identifier = "table";
Start with "$identifier is a(n)": "table is a(n)" ${typename} *(*${declaration}())[30];
Go right: "... function returning" ${typename} *(* ${declaration} )[30];
Go right: fails, because of )
Go left: "... pointer(s) to" ${typename} * ${declaration} [30];
Go right: "... an array of 30" ${typename} * ${declaration};
Go right: fails, because of ; ${typename} * ${declaration}
Go left: "... pointer(s) to" ${typename} ${declaration}
Go right: fails.
Go left: "int"
Write that all in order, and you get:
table is a(n) function returning pointer(s) to an array of 30 pointer(s) to int
Clean up the sentence by removing (s) where not needed, and replacing single pointer with "a pointer":
table is a function returning a pointer to an array of 30 pointers to int.

The identifier table is a function which returns a pointer to an array of 30 integer pointers. As a complement to learning the so called clockwise/spiral rule, you can use a site like http://cdecl.org/ to find out.
If I was able to rewrite the code I would split the declaration into a type declaration and a function declaration. That way it will be easier to understand the program text. Also I would call the result type Table and choose a more specific name for the function, which most likely returns a special kind of table, say a Foo table. If possible I would also avoid the empty parameter list and use the keyword void to specify that the function takes no parameters:
typedef int *(*Table)[30];
Table FooTable(void);

Above declaration can be understood by the Clockwise/Spiral rule.
Following describes how to parse the declaration using the rule:
1) table is a function with unspecified arguments.
2) The table() function returns a pointer.
3) The pointer returned by table() function points to an array of 30 elements.
4) Each element is of type integer pointers i.e., each element is pointing to an integer.
More about the rule is well explained in this link : The ``Clockwise/Spiral Rule''

Related

C isn't that hard: void ( *( *f[] ) () ) ()

I just saw a picture today and think I'd appreciate explanations. So here is the picture:
Transcription: "C isn't that hard: void (*(*f[])())() defines f as an array of unspecified size, of pointers to functions that return pointers to functions that return void."
I found this confusing and wondered if such code is ever practical. I googled the picture and found another picture in this reddit entry, and here is that picture:
Transcription: "So the symbols can be read: f [] * () * () void. f is an array of pointers that take no argument and return a pointer that takes no argument and returns void".
So this "reading spirally" is something valid? Is this how C compilers parse?
It'd be great if there are simpler explanations for this weird code.
Apart from all, can this kind of code be useful? If so, where and when?
There is a question about "spiral rule", but I'm not just asking about how it's applied or how expressions are read with that rule. I'm questioning usage of such expressions and spiral rule's validity as well. Regarding these, some nice answers are already posted.
There is a rule called the "Clockwise/Spiral Rule" to help find the meaning of a complex declaration.
From c-faq:
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
[X] or []
=> Array X size of... or Array undefined size of...
(type1, type2)
=> function passing type1 and type2 returning...
*
=> pointer(s) to...
Keep doing this in a spiral/clockwise direction until all tokens have been covered.
Always resolve anything in parenthesis first!
You can check the link above for examples.
Also note that to help you there is also a website called:
http://www.cdecl.org
You can enter a C declaration and it will give its english meaning. For
void (*(*f[])())()
it outputs:
declare f as array of pointer to function returning pointer to function returning void
EDIT:
As pointed out in the comments by Random832, the spiral rule does not address array of arrays and will lead to a wrong result in (most of) those declarations. For example for int **x[1][2]; the spiral rule ignores the fact that [] has higher precedence over *.
When in front of array of arrays, one can first add explicit parentheses before applying the spiral rule. For example: int **x[1][2]; is the same as int **(x[1][2]); (also valid C) due to precedence and the spiral rule then correctly reads it as "x is an array 1 of array 2 of pointer to pointer to int" which is the correct english declaration.
Note that this issue has also been covered in this answer by James Kanze (pointed out by haccks in the comments).
The "spiral" rule kind of falls out of the following precedence rules:
T *a[] -- a is an array of pointer to T
T (*a)[] -- a is a pointer to an array of T
T *f() -- f is a function returning a pointer to T
T (*f)() -- f is a pointer to a function returning T
The subscript [] and function call () operators have higher precedence than unary *, so *f() is parsed as *(f()) and *a[] is parsed as *(a[]).
So if you want a pointer to an array or a pointer to a function, then you need to explicitly group the * with the identifier, as in (*a)[] or (*f)().
Then you realize that a and f can be more complicated expressions than just identifiers; in T (*a)[N], a could be a simple identifier, or it could be a function call like (*f())[N] (a -> f()), or it could be an array like (*p[M])[N], (a -> p[M]), or it could be an array of pointers to functions like (*(*p[M])())[N] (a -> (*p[M])()), etc.
It would be nice if the indirection operator * was postfix instead of unary, which would make declarations somewhat easier to read from left to right (void f[]*()*(); definitely flows better than void (*(*f[])())()), but it's not.
When you come across a hairy declaration like that, start by finding the leftmost identifier and apply the precedence rules above, recursively applying them to any function parameters:
f -- f
f[] -- is an array
*f[] -- of pointers ([] has higher precedence than *)
(*f[])() -- to functions
*(*f[])() -- returning pointers
(*(*f[])())() -- to functions
void (*(*f[])())(); -- returning void
The signal function in the standard library is probably the type specimen for this kind of insanity:
signal -- signal
signal( ) -- is a function with parameters
signal( sig, ) -- sig
signal(int sig, ) -- which is an int and
signal(int sig, func ) -- func
signal(int sig, *func ) -- which is a pointer
signal(int sig, (*func)(int)) -- to a function taking an int
signal(int sig, void (*func)(int)) -- returning void
*signal(int sig, void (*func)(int)) -- returning a pointer
(*signal(int sig, void (*func)(int)))(int) -- to a function taking an int
void (*signal(int sig, void (*func)(int)))(int); -- and returning void
At this point most people say "use typedefs", which is certainly an option:
typedef void outerfunc(void);
typedef outerfunc *innerfunc(void);
innerfunc *f[N];
But...
How would you use f in an expression? You know it's an array of pointers, but how do you use it to execute the correct function? You have to go over the typedefs and puzzle out the correct syntax. By contrast, the "naked" version is pretty eyestabby, but it tells you exactly how to use f in an expression (namely, (*(*f[i])())();, assuming neither function takes arguments).
In C, declaration mirrors usage—that’s how it’s defined in the standard. The declaration:
void (*(*f[])())()
Is an assertion that the expression (*(*f[i])())() produces a result of type void. Which means:
f must be an array, since you can index it:
f[i]
The elements of f must be pointers, since you can dereference them:
*f[i]
Those pointers must be pointers to functions taking no arguments, since you can call them:
(*f[i])()
The results of those functions must also be pointers, since you can dereference them:
*(*f[i])()
Those pointers must also be pointers to functions taking no arguments, since you can call them:
(*(*f[i])())()
Those function pointers must return void
The “spiral rule” is just a mnemonic that provides a different way of understanding the same thing.
So this "reading spirally" is something valid?
Applying spiral rule or using cdecl are not valid always. Both fails in some cases. Spiral rule works for many cases, but it is not universal.
To decipher complex declarations remember these two simple rules:
Always read declarations from inside out: Start from innermost, if any, parenthesis. Locate the identifier that's being declared, and start deciphering the declaration from there.
When there is a choice, always favour [] and () over *: If * precedes the identifier and [] follows it, the identifier represents an array, not a pointer. Likewise, if * precedes the identifier and () follows it, the identifier represents a function, not a pointer. (Parentheses can always be used to override the normal priority of [] and () over *.)
This rule actually involves zigzagging from one side of the identifier to the other.
Now deciphering a simple declaration
int *a[10];
Applying rule:
int *a[10]; "a is"
^
int *a[10]; "a is an array"
^^^^
int *a[10]; "a is an array of pointers"
^
int *a[10]; "a is an array of pointers to `int`".
^^^
Let's decipher the complex declaration like
void ( *(*f[]) () ) ();
by applying the above rules:
void ( *(*f[]) () ) (); "f is"
^
void ( *(*f[]) () ) (); "f is an array"
^^
void ( *(*f[]) () ) (); "f is an array of pointers"
^
void ( *(*f[]) () ) (); "f is an array of pointers to function"
^^
void ( *(*f[]) () ) (); "f is an array of pointers to function returning pointer"
^
void ( *(*f[]) () ) (); "f is an array of pointers to function returning pointer to function"
^^
void ( *(*f[]) () ) (); "f is an array of pointers to function returning pointer to function returning `void`"
^^^^
Here is a GIF demonstrating how you go (click on image for larger view):
The rules mentioned here is taken from the book C Programming A Modern Approach by K.N KING.
It's only a "spiral" because there happens to be, in this declaration, only one operator on each side within each level of parentheses. Claiming that you proceed "in a spiral" generally would suggest you alternate between arrays and pointers in the declaration int ***foo[][][] when in reality all of the array levels come before any of the pointer levels.
I doubt constructions like this can have any use in real life. I even detest them as interview questions for the regular developers (likely OK for compiler writers). typedefs should be used instead.
As a random trivia factoid, you might find it amusing to know that there's an actual word in English to describe how C declarations are read: Boustrophedonically, that is, alternating right-to-left with left-to-right.
Reference: Van der Linden, 1994 - Page 76
Regarding the usefulness of this, when working with shellcode you see this construct a lot:
int (*ret)() = (int(*)())code;
ret();
While not quite as syntactically complicated, this particular pattern comes up a lot.
More complete example in this SO question.
So while the usefulness to the extent in the original picture is questionable (I would suggest that any production code should be drastically simplified), there are some syntactical constructs that do come up quite a bit.
The declaration
void (*(*f[])())()
is just an obscure way of saying
Function f[]
with
typedef void (*ResultFunction)();
typedef ResultFunction (*Function)();
In practice, more descriptive names will be needed instead of ResultFunction and Function. If possible I would also specify the parameter lists as void.
I happen to be the original author of the spiral rule that I wrote oh so many years ago (when I had a lot of hair :) and was honored when it was added to the cfaq.
I wrote the spiral rule as a way to make it easier for my students and colleagues to read the C declarations "in their head"; i.e., without having to use software tools like cdecl.org, etc. It was never my intent to declare that the spiral rule be the canonical way to parse C expressions. I am though, delighted to see that the rule has helped literally thousands of C programming students and practitioners over the years!
For the record,
It has been "correctly" identified numerous times on many sites, including by Linus Torvalds (someone whom I respect immensely), that there are situations where my spiral rule "breaks down". The most common being:
char *ar[10][10];
As pointed out by others in this thread, the rule could be updated to say that when you encounter arrays, simply consume all the indexes as if written like:
char *(ar[10][10]);
Now, following the spiral rule, I would get:
"ar is a 10x10 two-dimensional array of pointers to char"
I hope the spiral rule carries on its usefulness in learning C!
P.S.:
I love the "C isn't hard" image :)
I found method described by Bruce Eckel to be helpful and easy to follow:
Defining a function pointer
To define a pointer to a function that has no arguments and no return
value, you say:
void (*funcPtr)();
When you are looking at a complex definition like
this, the best way to attack it is to start in the middle and work
your way out. “Starting in the middle” means starting at the variable
name, which is funcPtr. “Working your way out” means looking to the
right for the nearest item (nothing in this case; the right
parenthesis stops you short), then looking to the left (a pointer
denoted by the asterisk), then looking to the right (an empty argument
list indicating a function that takes no arguments), then looking to
the left (void, which indicates the function has no return value).
This right-left-right motion works with most declarations.
To review, “start in the middle” (“funcPtr is a ...”), go to the right
(nothing there – you're stopped by the right parenthesis), go to the
left and find the ‘*’ (“... pointer to a ...”), go to the right and
find the empty argument list (“... function that takes no arguments
... ”), go to the left and find the void (“funcPtr is a pointer to a
function that takes no arguments and returns void”).
You may wonder why *funcPtr requires parentheses. If you didn't use
them, the compiler would see:
void *funcPtr();
You would be declaring a function (that returns a
void*) rather than defining a variable. You can think of the compiler
as going through the same process you do when it figures out what a
declaration or definition is supposed to be. It needs those
parentheses to “bump up against” so it goes back to the left and finds
the ‘*’, instead of continuing to the right and finding the empty
argument list.
Complicated declarations & definitions
As an aside, once you figure out how the C and C++ declaration syntax
works you can create much more complicated items. For instance:
//: C03:ComplicatedDefinitions.cpp
/* 1. */ void * (*(*fp1)(int))[10];
/* 2. */ float (*(*fp2)(int,int,float))(int);
/* 3. */ typedef double (*(*(*fp3)())[10])();
fp3 a;
/* 4. */ int (*(*f4())[10])();
int main() {} ///:~
Walk through each one and use the right-left
guideline to figure it out. Number 1 says “fp1 is a pointer to a
function that takes an integer argument and returns a pointer to an
array of 10 void pointers.”
Number 2 says “fp2 is a pointer to a function that takes three
arguments (int, int, and float) and returns a pointer to a function
that takes an integer argument and returns a float.”
If you are creating a lot of complicated definitions, you might want
to use a typedef. Number 3 shows how a typedef saves typing the
complicated description every time. It says “An fp3 is a pointer to a
function that takes no arguments and returns a pointer to an array of
10 pointers to functions that take no arguments and return doubles.”
Then it says “a is one of these fp3 types.” typedef is generally
useful for building complicated descriptions from simple ones.
Number 4 is a function declaration instead of a variable definition.
It says “f4 is a function that returns a pointer to an array of 10
pointers to functions that return integers.”
You will rarely if ever need such complicated declarations and
definitions as these. However, if you go through the exercise of
figuring them out you will not even be mildly disturbed with the
slightly complicated ones you may encounter in real life.
Taken from: Thinking in C++ Volume 1, second edition, chapter 3, section "Function Addresses" by Bruce Eckel.
Remember these rules for C declares
And precedence never will be in doubt:
Start with the suffix, proceed with the prefix,
And read both sets from the inside, out.
-- me, mid-1980's
Except as modified by parentheses, of course. And note that the syntax for declaring these exactly mirrors the syntax for using that variable to get an instance of the base class.
Seriously, this isn't hard to learn to do at a glance; you just have to be willing to spend some time practising the skill. If you're going to maintain or adapt C code written by other people, it's definitely worth investing that time. It's also a fun party trick for freaking out other programmers who haven't learned it.
For your own code: as always, the fact that something can be written as a one-liner does't mean it should be, unless it is an extremely common pattern that has become a standard idiom (such as the string-copy loop). You, and those who follow you, will be much happier if you build complex types out of layered typedefs and step-by-step dereferences rather than relying on your ability to generate and parse these "at one swell foop." Performance will be just as good, and code readability and maintainability will be tremendously better.
It could be worse, you know. There was a legal PL/I statement that started with something like:
if if if = then then then = else else else = if then ...
void (*(*f[]) ()) ()
Resolving void >>
(*(*f[]) ()) () = void
Resoiving () >>
(*(*f[]) ()) = function returning (void)
Resolving * >>
(*f[]) () = pointer to (function returning (void) )
Resolving () >>
(*f[]) = function returning (pointer to (function returning (void) ))
Resolving * >>
f[] = pointer to (function returning (pointer to (function returning
(void) )))
Resolving [ ] >>
f = array of (pointer to (function returning (pointer to (function
returning (void) ))))

what is foo in int **foo[][]()

I am currently studying for my C-Midterm and I encountered this declaration:
int **foo[][]()
When looking for the solution as to what this declaration means my tutors actually gave two different answers:
1) foo is an array of arrays of functions with return type pointer to pointer to an int
2) foo is an array of arrays of pointers to pointers to a function with return type int
I know the "start with the name of the variable, continue to the right until you reach the end or ')' then go back to your last starting point and continue to the left until you reach the start or '('" rule so I think 1) is the correct answer here but I am not entirely sure.
Thanks,
Ozelotl
It is nothing specific. Meaning that on the surface it looks like a C declaration, but it is not well-formed. It is illegal and as such it means nothing.
Firstly, it appears like a two-dimensional array declaration, but in C language an array declaration is required to specify all sizes except possibly for the very first one. Your declaration omits the second size as well, which makes it illegal.
Secondly, even if we ignore the missing sizes, it looks like a declaration for an array of functions. It is illegal to declare arrays of functions in C.
For example, this would make a legal C declaration
int (**foo[][42])()
but not what you have originally.
The syntax of this declaration is that foo[][] declares a 2-D array (or it would, if the second bound had a dimension specified - as it stands that's illegal); and then the rest of it is:
int **bar(); // with bar = foo[][]
which is a function taking unspecified arguments and returning int **. However, since bar is an array type here this attempts to declare an array of functions, which is illegal. (Not to be confused with an array of function pointers, which would be OK).
The grammar rules are that the ** bind to the int (not to the bar) unless you use parentheses to force them to bind to the bar; so they are part of the type int ** and they are not saying that bar is a pointer.

What is the meaning of the declaration "char (* ( *f())[])();"?

I was grabbing information about pointers to functions when I found this declaration:
char (* ( *f())[])();
I tried to find out what is the meaning of it but I couldn't...
what does it refer to?
It breaks down as follows:
f -- f
f() -- is a function returning
*f() -- a pointer to
(*f())[] -- an array of
*(*f())[] -- pointer to
(*(*f())[])() -- function returning
char (*(*f())[])(); -- char
Postfix operators like [] and function call () bind before unary operators like *, so
*a[] -- is an array of pointer
(*a)[] -- is a pointer to an array
*f() -- is a function returning a pointer
(*f)() -- is a pointer to a function
Find the leftmost identifier and work your way out, applying those rules recursively for any function parameters.
Edit
In the comment to another answer, KerrekSB suggests using typedefs, which would certainly make the code scan more easily:
typedef char CharFunc();
typedef CharFunc *CharFuncPtr;
typedef CharFuncPtr CharFuncPtrArr[N];
typedef CharFuncPtrArr *CharFuncPtrArrPtr;
typedef CharFuncPtrArrPtr CharFuncPtrArrPtrFunc();
CharFuncPtrArrPtrFunc *f;
You could probably come up with a better naming convention. But even so,
CharFuncPtrArrPtrFunc *f;
sure looks nicer than
char (*(*f())[])();
But is it better?
In my experience, the answer is often "no", especially when pointer types are involved. What is the function that f points to supposed to look like? How do I call it? What parameters am I supposed to pass to it? What do I do with the value returned by the function f points to? How do I use it in an expression? I have to look up the definition of CharFuncPtrArrPtrFunc, which means I also have to look up the definition of CharFuncPtrArrPtr, and CharFuncPtrArr, etc., etc., etc., then I have to mentally puzzle out the resulting syntax for the call.
char (*(*f())[])(); borders on total unreadability, but it tells me at a glance how I should call the function f points to and how to use the return value.
declare f as function returning pointer to array of pointer to function returning char

The spiral rule about declarations — when is it in error?

I recently learned the spiral rule for deobfuscating complex declarations, that should have been written with a series of typedefs. However, the following comment alarms me:
A frequently cited simplification, which only works for a few simple cases.
I do not find void (*signal(int, void (*fp)(int)))(int); a "simple case". Which is all the more alarming, by the way.
So, my question is, in which situations will I be correct to apply the rule, and in which it would be in error?
Basically speaking, the rule simply doesn't work, or else it
works by redefining what is meant by spiral (in which case,
there's no point in it. Consider, for example:
int* a[10][15];
The spiral rule would give a is an array[10] of pointer to
array[15] of int, which is wrong. It the case you cite, it
doesn't work either; in fact, in the case of signal, it's not
even clear where you should start the spiral.
In general, it's easier to find examples of where the rule fails
than examples where it works.
I'm often tempted to say that parsing a C++ declaration is
simple, but nobody who has tried with complicated declarations
would believe me. On the other hand, it's not as hard as it is
sometimes made out to be. The secret is to think of the
declaration exactly as you would an expression, but with a lot
less operators, and a very simple precedence rule: all operators
to the right have precedence over all operators to the left. In
the absence of parentheses, this means process everything to the
right first, then everything to the left, and process
parentheses exactly as you would in any other expression. The
actual difficulty is not the syntax per se, but that it
results is some very complex and counterintuitive declarations,
in particular where function return values and pointers to
functions are involved: the first right, then left rule means
that operators at a particular level are often widely separated,
e.g.:
int (*f( /* lots of parameters */ ))[10];
The final term in the expansion here is int[10], but putting
the [10] after the complete function specification is (at
least to me) very unnatural, and I have to stop and work it out
each time. (It's probably this tendency for logically adjacent
parts to spread out that lead to the spiral rule. The problem
is, of course, that in the absence of parentheses, they don't
always spread out—anytime you see [i][j], the rule is go
right, then go right again, rather than spiral.)
And since we're now thinking of declarations in terms of
expressions: what do you do when an expression becomes too
complicated to read? You introduce intermediate variables in order
to make it easier to read. In the case of declarations, the
"intermediate variables" are typedef. In particular, I would
argue that any time part of the return type ends up after the
function arguments (and a lot of other times as well), you
should use a typedef to make the declaration simpler. (This
is a "do as I say, not as I do" rule, however. I'm afraid that
I'll occasionally use some very complex declarations.)
The rule is correct. However, one should be very careful in applying it.
I suggest to apply it in a more formal way for C99+ declarations.
The most important thing here is to recognize the following recursive structure of all declarations (const, volatile, static, extern, inline, struct, union, typedef are removed from the picture for simplicity but can be added back easily):
base-type [derived-part1: *'s] [object] [derived-part2: []'s or ()]
Yep, that's it, four parts.
where
base-type is one of the following (I'm using a bit compressed notation):
void
[signed/unsigned] char
[signed/unsigned] short [int]
signed/unsigned [int]
[signed/unsigned] long [long] [int]
float
[long] double
etc
object is
an identifier
OR
([derived-part1: *'s] [object] [derived-part2: []'s or ()])
* is *, denotes a reference/pointer and can be repeated
[] in derived-part2 denotes bracketed array dimensions and can be repeated
() in derived-part2 denotes parenthesized function parameters delimited with ,'s
[] elsewhere denotes an optional part
() elsewhere denotes parentheses
Once you've got all 4 parts parsed,
[object] is [derived-part2 (containing/returning)] [derived-part2 (pointer to)] base-type 1.
If there's recursion, you find your object (if there's any) at the bottom of the recursion stack, it'll be the inner-most one and you'll get the full declaration by going back up and collecting and combining derived parts at each level of recursion.
While parsing you may move [object] to after [derived-part2] (if any). This will give you a linearized, easy to understand, declaration (see 1 above).
Thus, in
char* (**(*foo[3][5])(void))[7][9];
you get:
base-type = char
level 1: derived-part1 = *, object = (**(*foo[3][5])(void)), derived-part2 = [7][9]
level 2: derived-part1 = **, object = (*foo[3][5]), derived-part2 = (void)
level 3: derived-part1 = *, object = foo, derived-part2 = [3][5]
From there:
level 3: * [3][5] foo
level 2: ** (void) * [3][5] foo
level 1: * [7][9] ** (void) * [3][5] foo
finally, char * [7][9] ** (void) * [3][5] foo
Now, reading right to left:
foo is an array of 3 arrays of 5 pointers to a function (taking no params) returning a pointer to a pointer to an array of 7 arrays of 9 pointers to a char.
You could reverse the array dimensions in every derived-part2 in the process as well.
That's your spiral rule.
And it's easy to see the spiral. You dive into the ever more deeply nested [object] from the left and then resurface on the right only to note that on the upper level there's another pair of left and right and so on.
The spiral rule is actually an over-complicated way of looking at it. The actual rule is much simpler:
postfix is higher precedence than prefix.
That's it. That's all you need to remember. The 'complex' cases are when you have parenthesis to override that postfix-higher-than-prefix precedence, but you really just need to find the matching parenthesis, then look at the things inside the parens first, and, if that is not complete, pull in the next level outside the parenthses, postfix first.
So looking at your complex example
void (*signal(int, void (*fp)(int)))(int);
we can start at any name and figure out what that name is. If you start at int, you're done -- int is a type and you can understand it by itself.
If you start at fp, fp is not a type, its a name being declared as something. So look at the first set of parens enclosing:
(*fp)
there's no suffix (deal with postfix first), then the prefix * means pointer. Pointer to what? not complete yet so look out another level
void (*fp)(int)
The suffix first is "function taking an int param", then the prefix is "returning void". So we have fn is "pointer to function taking int param, returning void"
If we start a signal, the first level has a suffix (function) and a prefix (returning pointer). Need the next level out to see what that points to (function returning void). So we end up with "function with two params (int and pointer to function), returning pointer to function with one (int) param, returning void"
E.g.:
int * a[][5];
This is not an array of pointers to arrays of int.

How do you read C declarations?

I have heard of some methods, but none of them have stuck. Personally I try to avoid complex types in C and try to break them into component typedef.
I'm now faced with maintaining some legacy code from a so called 'three star programmer', and I'm having a hard time reading some of the ***code[][].
How do you read complex C declarations?
This article explains a relatively simple 7 rules which will let you read any C declaration, if you find yourself wanting or needing to do so manually: http://www.ericgiguere.com/articles/reading-c-declarations.html
Find the identifier. This is your starting point. On a piece of paper, write "declare identifier as".
Look to the right. If there is nothing there, or there is a right parenthesis ")", goto step 4.
You are now positioned either on an array (left bracket) or function (left parenthesis) descriptor. There may be a sequence of these, ending either with an unmatched right parenthesis or the end of the declarator (a semicolon or a "=" for initialization). For each such descriptor, reading from left to right:
if an empty array "[]", write "array of"
if an array with a size, write "array size of"
if a function "()", write "function returning"
Stop at the unmatched parenthesis or the end of the declarator, whichever comes first.
Return to the starting position and look to the left. If there is nothing there, or there is a left parenthesis "(", goto step 6.
You are now positioned on a pointer descriptor, "*". There may be a sequence of these to the left, ending either with an unmatched left parenthesis "(" or the start of the declarator. Reading from right to left, for each pointer descriptor write "pointer to". Stop at the unmatched parenthesis or the start of the declarator, whichever is first.
At this point you have either a parenthesized expression or the complete declarator. If you have a parenthesized expression, consider it as your new starting point and return to step 2.
Write down the type specifier. Stop.
If you're fine with a tool, then I second the suggestion to use the program cdecl: http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html
I generally use what is sometimes called the 'right hand clockwise rule'.
It goes like this:
Start from the identifier.
Go to the immediate right of it.
Then move clockwise and come to the left hand side.
Move clockwise and come to the right side.
Do this as long as the declaration has not been parsed fully.
There's an additional meta-rule that has to be taken care of:
If there are parentheses, complete each level of parentheses before moving out.
Here, 'going' and 'moving' somewhere means reading the symbol there. The rules for that are:
* - pointer to
() - function returning
(int, int) - function taking two ints and returning
int, char, etc. - int, char, etc.
[] - array of
[10] - array of ten
etc.
So, for example, int* (*xyz[10])(int*, char) is read as:
xyz is an
array of ten
pointer to
function taking an int* and a char and returning
an int*
One word: cdecl
Damnit, beaten by 15 seconds!
Cdecl (and c++decl) is a program for encoding and decoding C (or C++) type declarations.
http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html
Back when I was doing C, I made use of a program called "cdecl". It appears that it's in Ubuntu Linux in the cutils or cdecl package, and it's probably available elsewhere.
cdecl offers a command line interface so let's give it a try:
cdecl> explain int ***c[][]
declare c as array of array of pointer to pointer to pointer to int
another example
explain int (*IMP)(ID,SEL)
declare IMP as pointer to function (ID, SEL) returning int
However there is a whole chapter about that in the book "C Deep Secrets", named "Unscrambling declarations in C.
Just came across an illuminating section in "The Development of the C Language":
For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,
int i, *pi, **ppi;
declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly,
int f(), *f(), (*f)();
declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer;
int *api[10], (*pai)[10];
declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.
There's also a Web-based version of cdecl which is pretty slick.
Common readability problems include function pointers and the fact that arrays are really pointers, and that multidimensional arrays are really single dimension arrays (which are really pointers). Hope that helps some.
In any case, whenever you do understand the declarations, maybe you can figure out a way to simplify them to make them more readable for the next guy.
Automated solution is cdecl.
In general, you declare a variable the way you use it. For example, you dereference a pointer p as in:
char c = * p
you declare it in a similar looking way:
char * p;
Same goes for hairy function pointers. Let's declare f to be good old "pointer to function returning pointer to int," and an external declaration just to be funny. It's a pointer to a function, so we start with:
extern * f();
It returns a pointer to an int, so somewhere in front there there's
extern int * * f(); // XXX not quite yet
Now which is the correct associativity? I can never remember, so use some parenthesis.
extern (int *)(* f)();
Declare it the way you use it.

Resources