При объявлении переменных, массивов, указателей или функций кроме простых идентификаторов могут использоваться составные описатели.
Составной описатель – это идентификатор, дополненный более чем одним признаком массива, функции или указателя.
Порядок интерпретации составных описателей.
1. В состав любого описателя должен входить идентификатор, он ищется на первом шаге.
2. Рассматриваются квадратные (признак массива) и круглые (признак функции) скобки справа от идентификатора, они имеют одинаковый приоритет и интерпретируются слева направо от окончания идентификатора
3. Затем справа налево рассматриваются знаки указателя, расположенные слева от идентификатора.
4. Интерпретируется спецификация типа идентификатора.
Для изменения порядка интерпретации можно использовать круглые скобки. Если при выполнении пункта 2 справа встречается закрывающая круглая скобка, то нужно переходить к пункту 3 для той части описателя, которая заключена между этой закрывающей круглой скобкой и соответствующей ей открывающей, а затем продолжать интерпретацию, начиная с пункта 2, но уже для объекта, заключённого в круглые скобки.
Пример 1
int (*(*v)[4])[5]
6 4 21 3 5
Идентификатор v (1) – это указатель (2) на массив (3) из 4 указателей (4) на массивы (5) из 5 чисел типа int (6).
Пример 2
float* (*f[4])(int*, char*(*)(float))
11 10 312 4 5 9 6 78
Идентификатор f (1) – это массив (2) из 4 указателей (3) на функции (4), которые принимают в качестве аргументов указатель на число типа int (5) и указатель (6) на функцию (7), принимающую в качестве аргумента переменную типа float (8) и возвращающую указатель типа char (9), и функции (4) возвращают указатели (10) типа float (11).