Это объявление начинается спецификатором typedef, содержит спецификатор объявления int и список описателей, в который входит два элемента: имя Step и имя pInteger, перед которым стоит символ ptrОперации *.
Объявление эквивалентно паре typedef-объявлений следующего вида: typedef int Step; typedef int *pInteger;
В соответствии с typedef-объявлениями, транслятор производит серию подстановок, суть которых становится понятной из анализа примера, в котором пара операторов объявления Step StepVal; extern pInteger pVal;
заменяется следующими объявлениями: int StepVal; extern int * pVal;
На основе этого примера можно попытаться воспроизвести алгоритм подстановки:
Если в программе присутствует typedef-объявление typedef char* (*PPFF) (int,int,int*,float);
то компактное объявление функции PPFF ReturnerF(int, int);
преобразуется при трансляции в сложное, но как мы далее увидим, абсолютно корректное объявление: char* (*ReturnerF(int, int))(int,int,int*,float);
При этом по идентификатору PPFF в прототипе функции находится контекст замены char* (*PPFF) (int,int,int*,float), в котором замещаемый описатель PPFF заменяется замещающим описателем ReturnerF(int, int).
Цель достигнута. Простое становится сложным. И как хорошо, что всё это происходит без нашего участия! Перед нами очередное средство для "облегчения" труда программиста.
Заметим, что подстановка возможна и в том случае, когда замещаемый описатель заменяется пустым замещающим описателем.
То же самое typedef-объявление позволяет построить следующее объявление функции: void MyFun (int, int, int*, float, PPFF);