

Intuitive Understanding of C Declaration
Useful "Right-Left" rule for deciphering complex declaration in C programming language
Overview
This article describes several examples of declaration in C programming considering the order of symbols, identifiers and explaining with an intuitive understanding.
For instance, converting this declaration
int (*(*func_ptr)(char *,double))[9][20];cto plain text English
func_ptr is pointer to function expecting (char *,double) and returning pointer to array (size 9) of array (size 20) of int.
Prerequisite
- Basic understanding of programming language
An understanding of C programming language syntax, data type, identifier and the concept of pointers is advantageous, but not required.
The “Right-Left” rule Intuition
First and foremost, these symbols in C are important: asterisk ”*”, squared bracket ”[]”, and parenthesis ”()”.
Later, these can be useful to determine the correct declaration by using their translated English interpretation and their position in the declaration sentence.
| Symbol | Interpretation | Position |
|---|---|---|
| * | as “pointer to” | on the left side |
| [] | as “array of” | on the right side |
| () | as “function returning” | on the right side |
These symbols can be interpreted in plain English whose position can also be interpreted to order all symbols
Step 1 – Find the Identifier
Take int *p[]; as a basic example which can be interpreted straight forward by looking from the previous Symbol-English translation table and is an array of pointers to data type int.
int *p[];
^cHere the Identifier is p and is simply intepreted as “p is”.
Step 2 – Read all symbols to the right
Next, continue with symbols on the right of the Identifier until there is no symbol remaining OR encountering a right parenthesis.
From the Symbol-English table, the ”[]” appended after the Identifier is interpreted as “Identifier is array of” or in the case of ”()” is “Identifier is function returning”.
int *p[];
^^cHere the squared bracket is [] encountered and can be intepreted as “p is array of”.
A special case of multiple left parenthesis with nesting between the initial parentheses only means that the whole procedure is repeated.
Step 3 – Read all symbols to the left and then the data type
Once there is no symbol on the right, moving towards the data type starting at the Identifier, i.e. left direction, until there is no symbol remaining OR encountering a left parenthesis.
int *p[];
^cHere the asterisk is * encountered and can be intepreted as “p is array of pointer to”.
Lastly, if there is no symbol belong to the Symbol-English table left, evaluate the data type.
int *p[];
^^^cHere the data type is int encountered and can be intepreted as “p is array of pointer to int”.
Nested Declaration
Now using int *(*func())(); for declaration to address the nesting as previously mentioned.
// Step 1 - Find the Identifier
int *(*func())();
^^^^
// "func is"
// Step 2 - Read all symbols to the right
int *(*func())();
^^
// "func is"
// found "()", appending "function returning"
// Step 3 - Encounter right parenthesis,
// read all symbols to the left
int *(*func())();
^
// "func is function returning"
// found "*", appending "pointer to"
// Step 4 - Encounter left parenthesis,
// return to read all symbols to the right
int *(*func())();
^^
// "func is function returning pointer to"
// found "()", appending "function returning"
// Step 5 - No remaining symbols on the right,
// return to read all symbols to the left
int *(*func())();
^
// "func is function returning pointer to function returning"
// found "*", appending "pointer to"
// Step 6 - Finally, no remaining symbols on either sides,
// evaluate data type
int *(*func())();
^^^
// "func is function returning pointer to function returning pointer to"
// found data type, appending "int".cThe final result is “func is function returning pointer to function returning pointer to int”.
Illegal Declaration
Although not required upto this, knowledge of legal C declaration is necessary to avoid making illegal declaration eventhough they made sense in English-like interpretation.
| Pairs | Illegal combinations | Correct intepretation |
|---|---|---|
[ ]( ) | an array of functions | an array of pointers to functions |
( )( ) | a function returns a function | a function returns a pointer to a function |
( )[ ] | a function returns an array | a function returns a pointer to an array |
Interprete English-like declaration also required to make proper and valid declaration based on the C programming syntax
Take the first example from this article, strip down argument list and array size, and modify it as int *((*func_ptr)())[][];. Now this is interpreted as
func_ptr is pointer to function returning array of array of
^^^^^^^^^^^^^^^^^^^^^^^^
pointer to intcThis will cause error thrown despite made sense following the Right-Left rule, because technically a function cannot return an array, but rather the pointer to that array.
Acknowledgement
This tutorial is heavily influenced by Lecture Notes ↗ created by Mr. Rick Ord from the Computer Science and Engineering Department, UC San Diego in California, USA.