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