Here the grammar for the declarator is taken from the standard (& section 6.7.5):
declarator :
pointer opt direct-declarator
direct-declarator :
identifier
( declarator )
direct-declarator [ type-qualifier-list opt assignment-expression opt ]
direct-declarator [ static type-qualifier-list opt assignment-expression ]
direct-declarator [ type-qualifier-list static assignment-expression ]
direct-declarator [ type-qualifier-list opt * ]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list opt )
pointer :
* type-qualifier-list opt
* type-qualifier-list opt pointer
type-qualifier-list :
type-qualifier
type-qualifier-list type-qualifier
parameter-type-list :
parameter-list
parameter-list , ...
parameter-list :
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration :
declaration-specifiers declarator
declaration-specifiers abstract-declarator opt
identifier-list :
identifier
identifier-list , identifier
As you can see, both [] and () bound to the declarator before * . Take an ad
int *a[N];
The declaration *a[N] , which corresponds to the direct-declarator pointer of the opt pointer above, and thus is parsed as *(a[N]) , so a is an N-element array of the pointer.
Summarizing:
T *a[N] -- declares an N-element array of pointer to T T (*a)[N] -- declares a pointer to an N-element array of T T *f() -- declares a function returning pointer to T T (*f)() -- declares a pointer to a function returning T
source share