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

  1. Find the identifier. This is your starting point. On a piece of paper, write "declare identifier as".
  2. Look to the right. If there is nothing there, or there is a right parenthesis ")", goto step 4.
  3. 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.

  4. Return to the starting position and look to the left. If there is nothing there, or there is a left parenthesis "(", goto step 6.
  5. 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.
  6. 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.
  7. 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!