Информатика и технология программирования

         

Синтаксис указателя на функцию


Определение указателя на функцию имеет вид:


int (*pf)(); // без контроля параметров вызова


int (*pf)(int, char*); // с контролем по прототипу

Ввиду того, что "классический" Си предусматривает два вида синтаксиса определения и объявления функции - с контролем соответствия параметров при вызове (прототип) и без оного (анахронизм), то для указателя на функцию синтаксис также может быть двояким: с контролем типов формальных параметров и без него.

В соответствии с принципом контекстного определения типа данных эту конструкцию следует понимать так: pf -переменная, при косвенном обращении к которой получается вызов функции, возвращающей int в качестве результата, то есть pf -адрес функции или указатель на функцию. Следует обратить внимание на то, что в определении указателя присутствует тип результата - указатель ссылается не на произвольную функцию, а только на одну из функций, дающих результат этого типа. Перед началом работы с указателем его необходимо назначить на соответствующий объект, в данном случае - на функцию. В синтаксисе Си выражение вида &#38имя_функции имеет смысл -начальный адрес функции или указатель на функцию. Кроме того, по аналогии с именем массива использование имени функции без скобок интерпретируется как указатель на эту функцию. Указатель может быть инициализирован и при определении. Таким образом, возможны следующие способы назначения указателей:


int INC( int а) { return a+1; }
extern int DEC(int);
int (*pf)(int);
pf = &#38INC;
pf = INC; // присваивание указателя


int (*pp)(int) = &#38DEC; // инициализация указателя

Естественно, что функция, на которую формируется указатель, должна быть известна транслятору - определена или объявлена как внешняя. Синтаксис вызова функции по указателю совпадает с синтаксисом ее определения:


n = (*pf)(1) + (*pp)(n); // эквивалентно


n = INC(1) + DEC(n);

Указатели на функции могут входить в более сложные структуры данных. Следующий фрагмент программы показывает использование массива указателей для вычисления функции, имя которой вводится вместе со значением аргумента:




extern double sin(double);
extern double cos(double);
extern double tan(double);
char *names[] = { "sin","cos","tan",NULL};
double (*pf[])(double) = { sin, cos, tan};

Переменная pf представляет собой массив указателей на функции, инициализированный адресами библиотечных функций
sin, cos и tan .


double call(char *pn,int val)
// pn - имя вычисляемой функции

// val - значение аргумента

{
int i;
for (i=0; names[i]!=NULL; i++)
if (strcmp(names[i],pn) == 0)
{ // Имя найдено

return ((*pf[i])(val));
} // вызов функции по i-му

return(0.); // указателю в массиве pf

}

Содержание раздела