How To Read Complicated C Declarations
While reading up on C coding practices and learning the more esoteric parts of C, I've discovered a rather useful method for understanding long and complicated C declarations. Before i go on however, i must mention this isn't something i've invented, it's a method i've discovered which was documented by David Anderson in 1994.
Complicated declarations are the biggest grievance people have when reading C source code and are a major block to fully understanding the C language. Hopefully using this method, reading complicated C source files will be a more pleasant task.
Introducing 'The Clockwise Spiral' Method
This method is called the clockwise spiral because of the simple reason that you start at an unknown element and work your way out in a clockwise spiral reading the attached operators and other various tokens, building up a picture of the overall meaning of the declaration.
The Method Rules
- Starting with the unknown declaration name, move in a clockwise spiral direction. When ecountering the following elements replace them with the corresponding english statements.
- replace '[ ]' with 'array of undefined size of'
- replace '[x]' with 'array with x elements of'
- replace '( )' with 'function, returning'
- replace '(type1, type2)' with 'function passing type1, type2, returning'
- replace '*' with 'pointer(s) to'
- Keep doing this in a clockwise spiral direction until all elements have been covered.
- Always resolve anything in parenthesis first.
Examples
Let me show you an example. This is a simple declaration which i'll use to familiarise yourself with the spiral.
char *exp[10];

Each step of the spiral path encounters a different element of the declaration and simply replacing these elements with the text from the above list creates a sentence to read as English. In the above example following the spiral through 4 steps we create a sentence which reads 'exp is array with 10 elements of pointer(s) to char', and that's exactly what this declaration means.
Here's another more complicated declaration:
void (*prnt)(int);

Here, we are obeying method rule 3 (from above) which states 'Always resolve anything in parenthesis first'. So we resolve '*prnt' before moving forward. Again, after completing 4 steps of the spiral we end up with a sentence that reads 'prnt is pointer(s) to function passing int, returning void'. Each element we encounter along the spiral adds a little more to the final sentence.
Now, let's try a declaration which would tax most C developers:
char (*(*dpm[3])())[5];

It doesn't matter how complex the declaration is, the spiral will always work. Even if you run into complicated function definitions which take function definitions as arguments, you simply start another spiral on the arguments. Anywhere you see a declaration name you may start a spiral to decypher its meaning.
Try it yourself on declarations you're having trouble reading.
For those that are interested here is the original resource that inspired this post: http://c-faq.com/decl/spiral.anderson.html



