Spiral reading rule

Original author: David Anderson
  • Transfer
A technique known as “Clockwise / Spiral Rule” allows any programmer to parse any C language declaration.

Follow these simple steps:

1. Starting from an unknown element, move in a spiral / clockwise direction; at the same time replace the following elements with the appropriate phrases:
  • [X] or [] => an array of size X of type ... or an array of undefined size of type ...
  • (type1, type2) => function accepting types type1, type2 and returning ...
  • * => pointer to ...

2. Move in a spiral / clockwise direction until all elements have been completed.
3. Always first allow expressions in parentheses!

Example 1: Simple ad


                     +-------+

                     | +-+   |

                     | ^ |   |

                char *str[10];

                 ^   ^   |   |

                 |   +---+   |

                 +-----------+



We ask ourselves what is str?
str is ...

We move in a spiral / clockwise, starting with str, and the first character that we see is '[', then this is an array, and so:
str is an array of size 10 of type ...

We continue to move in a spiral / clockwise direction, and the next thing we meet is the symbol '*', which means we have pointers, and so:
str is an array of size 10 type pointer to ...

We move in a spiral and see the end of the line, so we move on and see the type 'char', and so:
str is an array of size 10 type pointer to char.

We visited all the elements, i.e. That's all, we made out this expression!

Example 2: Declaring a Function Pointer


                     +--------------------+

                     | +---+              |

                     | |+-+|              |

                     | |^ ||              |

                char *(*fp)( int, float *);

                 ^   ^ ^  ||              |

                 |   | +--+|              |

                 |   +-----+              |

                 +------------------------+


Ask yourself, what is fp?
fp is ...

We move in a spiral / clockwise, and the first thing we see is ')'; so fp is inside the brackets and we continue the spiral inside the brackets and the next character is '*', and so:
fp is a pointer to ...

We are now outside the brackets and, continuing to move in a spiral, we see '(', i.e. this is a function, and so:
fp is a pointer to a function that takes an int and a pointer to a float that returns ...

Continuing to move in a spiral, we meet the symbol '*', and so:
fp is a pointer to a function that takes an int and a pointer to a float that returns a pointer to ...

Continuing in a spiral, we encounter the symbol ';', but since not all the symbols have been processed yet, we continue and encounter 'char', and so:
fp is a pointer to a function that takes an int and a pointer to a float that returns a pointer to a char.


Example 3: Ultimate


                      +-----------------------------+

                      |                  +---+      |

                      |  +---+           |+-+|      |

                      |  ^   |           |^ ||      |

                void (*signal(int, void (*fp)(int)))(int);

                 ^    ^      |      ^    ^  ||      |

                 |    +------+      |    +--+|      |

                 |                  +--------+      |

                 +----------------------------------+


We ask ourselves, what is signal?
Note the signal inside the brackets, so you need to parse the expression inside! Moving in a spiral / clockwise direction, we see '(', and so:
signal is a function that takes int and ...

Hmm, we can use the same rule on the symbol 'fp', and so what is fp? fp is also inside the brackets, so we continue and see the '*', and so:
fp is a pointer to ...

Moving in a spiral / clockwise direction, we see '(', and so:
fp is a pointer to a function that takes an int, returns ...

Moving in a spiral / clockwise direction, we see 'void', and so:
fp is a pointer to a function that takes an int that returns void.

We are done with fp, so let's continue with signal, and now we have:
signal - a function that takes an int and a pointer to a function that takes an int, returns void, returns ...

We are still inside the brackets, so the next character is '*', and so:
signal - a function that takes an int and a pointer to a function that takes an int, returns void, returns a pointer to ...

We allowed the elements inside the brackets, continuing in a spiral we get the symbol '(', and so:
signal - a function that takes an int and a pointer to a function that takes an int, returns void, returns a pointer to a function that takes an int and returns ...

Finally, we continue to move, and with the last character we see 'void', and so, our full description is as follows:
signal - a function that takes an int and a pointer to a function that takes an int, returns void, returns a pointer to a function that takes an int and returns void.


This rule also applies to understanding the const and volatile attributes. For instance:
const char * chptr;

So what is chptr?
chptr is a pointer to char immutable.

What about this:
char * const chptr;

So what is chptr?
chptr is an immutable pointer to char.

And finally:
volatile char * const chptr;

So what is chptr?
chptr is an immutable pointer to char volatile.

Also popular now: