Конструкции массива и указателя при описании типа можно применять многократно в произвольном порядке. Кроме того, можно описывать прототип функции. Таким образом можно строить сложные описания вроде "массив указателей", "указатель на указатель", "указатель на массив", "функция, возвращающая значение типа указатель", "указатель на функцию" и т.д. Правила здесь таковы:
int *(x[10]);
означает "массив из 10 элементов типа указатель на int";
при отсутствии скобок приоритеты конструкций описания распределены следующим образом:
int *x[10];
означает "массив из 10 элементов типа указатель на int". Здесь к имени переменной x сначала применяется операция определения массива [] (квадратные скобки), поскольку она имеет более высокий приоритет, чем звездочка. Затем к полученному массиву применяется операция определения указателя. В результате получается "массив указателей", а не указатель на массив! Если нам нужно определить указатель на массив, то следует использовать круглые скобки при описании:
int (*x)[10];
Здесь к имени x сначала применяется операция * определения указателя;
int f();
Описан прототип функции f без аргументов, возвращающей значение типа int.
int (*f())[10];
Описан прототип функции f без аргументов, возвращающей значение типа указатель на массив из 10 элементов типа int;
void (*a[100])(int x);
Описывается переменная a. К ней сначала применяется операция описания массива из 100 элементов, далее - определение указателя, далее - функция от одного целочисленного аргумента x типа int, наконец - определение возвращаемого типа void. Описание читается следующим образом:
Ниже расставлены номера операций в порядке их применения в описании переменной a:
void (* a [100])(int x); 5) 3) 1) 2) 4)