Читайте также:
|
|
Указатели на функции – это указатели, т.е. переменные, которые указывают на адрес функции. Запущенная программа получает определённую область в оперативной памяти. И исполняемый скомпилированный программный код, и используемые переменные, размещаются в этой памяти.
Прежде чем вводить указатель на функцию, необходимо вспомнить, что каждая функция характеризуется типом возвращаемого значения, именем, количеством, порядком следования и типами параметров.
При использовании имени функции без последующих скобок и параметров имя функции выступает в качестве указателя на эту функцию, и его значением служит адрес размещения функции в памяти (как в случае с указателем на массив – имя массива является указателем на его первый элемент).
Это значение адреса может быть присвоено другому указателю, и затем уже этот новый указатель можно применять для вызова функции. Однако в определении нового указателя должен быть тот же тип, что и возвращаемое функцией значение, то же количество, порядок следования и типы параметров. Указатель на функцию определяется следующим образом:
Указатель на функцию определяется следующим образом:
тип функции (*имя_указателя)(спецификация_параметров);
Например:
int(*func1ptr) (char);
определение указателя func1ptr на функцию с параметром типа char, возвращающую значение типа int.
Если приведенную синтаксическую конструкцию записать без первых круглых скобок, то есть в виде
int *fun(char);
то компилятор воспримет ее как прототип некой функции с именем fun и параметром типа char, возвращающей значение указателя типа int *.
Второй пример:
char * (*func2Ptr) (char *, int);
определение указателя func2Ptr на функцию с параметрами типа указатель на char и типа int, возвращающую значение типа указатель на char.
В определении указателя на функцию тип возвращаемого значения и сигнатура (типы, количество и последовательность параметров) должны совпадать с соответствующими типами и сигнатурами тех функций, адреса которых предполагается присваивать вводимому указателю. В качестве простейшей иллюстрации – небольшой пример:
void f1()
{
printf_s("Выполняется f1()\n");
}
void f2()
{
printf_s("Выполняется f2()\n");
}
void main()
{
setlocale(LC_CTYPE, "rus");
void (*ptr)(void); // объявление указателя на функцию (ptr)
ptr = f2; // ptr инициализируется адресом f2()
(*ptr)(); // вызов f2() по ее адресу
ptr = f1; // присваивается адрес f1()
(*ptr)(); // вызов f1() по ее адресу
ptr(); // вызов эквивалентен (*ptr)();
printf_s("\n\nКонец!\n");
_getch();
}
Значением имени указателя служит адрес функции, а с помощью операции разыменования * обеспечивается обращение по адресу к этой функции. Однако будет ошибкой записать вызов функции без скобок в виде *ptr().
Дело в том, что операция () имеет более высокий приоритет, нежели операция обращения по адресу *. Следовательно, в соответствии с синтаксисом, будет вначале сделана попытка обратиться к функции ptr(). И уже к результату будет отнесена операция разыменования (*), что будет воспринято как синтаксическая ошибка.
Следующая программа иллюстрирует гибкость механизма вызовов функций с помощью указателей.
int Add(int n, int m)
{ return(n + m); }
int Div(int n, int m)
{ return(n % m); }
int Mult(int n, int m)
{ return(n * m); }
int Subt(int n, int m)
{ return(n - m); }
void main()
{
setlocale(LC_CTYPE, "rus");
int (*par)(int, int); // указатель на функцию
int a = 6, b = 2, val;
char c = '+';
printf_s("a = %d b = %d\n\n",a,b);
while(c!= ' ')
{
switch(c)
{
case '+':
par = Add; //par получает адрес функции add
//val = (*par)(a,b);
printf_s("%d %c %d = %d\n",a,c,b,(*par)(a,b));
c = '%';
break;
case '-':
par = Subt; //par получает адрес функции subt
val = (*par)(a,b);
printf_s("%d %c %d = %d\n",a,c,b,val);
c = ' ';
break;
case '*':
par = Mult; // par получает адрес функции mult
val = (*par)(a,b);
printf_s("%d %c %d = %d\n",a,c,b,val);
c = '-';
break;
case '%':
par = Div; // par получает адрес функции div
val = (*par)(a,b);
printf_s("%d %c %d = %d\n",a,c,b,val);
c = '*';
break;
}
_getch();
}
printf_s("\n\nКонец!\n");
_getch();
}
Цикл продолжается, пока значением переменной с не станет пробел. В каждой итерации указатель par получает адрес одной из функций, и изменяется значение с. По результатам программы легко проследить порядок выполнения ее операторов.
Дата добавления: 2015-07-24; просмотров: 42 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Реализация программы обычным способом | | | Объявления в средствах массовой информации |