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];
to 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 |
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[];
^
Here the Identifier is
p
and is simply intepreted as ”p is“.
NOTE: Identifier is a user-defined name/term and must not belong to keywords (pre-defined, reserved words).
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[];
^^
Here the squared bracket is
[]
encountered and can be intepreted as “p is array of“.
NOTE: 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[];
^
Here 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[];
^^^
Here 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".
The 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 |
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 int
This 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.