Symbols, like &
, *
, etc., are used in both expressions and declarations, which are two distinctive concepts.
In expressions, the symbols are operators, for which we have a well-defined table of precedence and associativity. When an expression is complex, we can decompose and analyze it using this table. e.g.
(a + b) * ++c
Question:
In declarations, these symbols are not operator and hence we cannot apply the table of precedence and associativity for operators. Is there a table of precedence and associativity for symbols in declarations?
Or in other words, when an declaration gets complicated (try this one int*& (*&f(int*))
), is there a systematic way to decompose and analyze it?
A closely related follow-up question:
Some book (primer) taught us how to read complex declaration with an example of typedef
:
typedef int (*tp_alias)[10]; //defines tp_alias as an pointer to an array of 10 int
Method taught by the book: use the the alias name as the starting point of reading, tp_alias
is the new type name. Looking to the left, it has a *
, so it is a pointer. Then look outside the parenthesis: to the right, [10]
means it is an array of size 10; to the left, int
means the element of the array is int.
Follow-up Question:
How do we read other type aliasing declaration, such as using
? Since the alias name is no longer in position? e.g. using tp_alias = int (*)[10]
?
Maybe to read from within the ()
, but whatif there is more than one ()
s?(I have not seen one but it is a possibility.)