Тип указатель: указатели на функции
Цель лекции: изучить указатели на функции и методы передачи функций как параметров, научиться использовать указатели на функции в программных кодах на языке C++.
Функции, как и элементы данных, имеют адреса. Адресом функции является адрес памяти, с которого начинается машинный код функции.
Для того, чтобы использовать в программе указатель на функцию, необходимо выполнить следующие действия:
- принять адрес функции;
- объявить указатель на функцию;
- использовать указатель на функцию для вызова этой функции.
Каждая функция характеризуется типом возвращаемого значения, именем и списком типов ее параметров. Если имя функции использовать без последующих скобок и параметров, то оно будет выступать в качестве указателя на эту функцию, и его значение будет определяться как адрес размещения функции в памяти (первый байт). Это значение можно будет присвоить другому указателю. Тогда этот новый указатель можно будет использовать для вызова функции. Указатель на функцию как переменная вводится отдельно от определения и объявления (прототипа) какой-либо функции.
Указатель на функцию – переменная, которая содержит адрес некоторой функции. Соответственно, косвенное обращение по этому указателю представляет собой вызов функции.
Синтаксис определения указателя на функцию:
тип_функции(*имя_указателя)(спецификация_параметров)
где тип_функции – определяет тип возвращаемого функцией значения; имя_указателя – идентификатор; спецификация_параметров – определяет состав и типы параметров функции.
Например:
int (*pf)(); // без контроля параметров вызова int (*pf)(void); // без параметров, с контролем по прототипу int (*pf)(int, char*); // с контролем по прототипу
В соответствии с принципом контекстного определения типа данных эту конструкцию следует понимать так: pf – переменная, при косвенном обращении к которой вызывается функция с соответствующим прототипом, например int_F(int, char*), то есть pf содержит адрес функции или указатель на функцию. Следует обратить внимание на то, что в определении указателя присутствует прототип – указатель ссылается не на произвольную функцию, а только на одну из функций с заданной схемой формальных параметров и результата.
В определении указателя количество и тип параметров должны совпадать с соответствующими типами в определении функции, на которую ставится указатель.
Например,
int (*func1Prt)(char);
задает определение указателя func1Prt на функцию с параметром типа char, возвращающую значение типа int.
Важнейшим элементом в определении указателя на функцию являются круглые скобки. Так следующий фрагмент:
int *func(char);
это не определение указателя, а объявление (прототип) функции c именем func и параметром типа char, возвращающей значение указателя типа int *. В этом случае указатель указывает на значение функции.
Если же выполнить объявление:
char *(*func2Prt)(char *,int);
то определение указателя func2Prt на функцию с параметрами типа указатель на char и типа int, возвращающую значение типа указатель на char.
Синтаксис вызова функции с помощью указателя:
(*имя_указателя)(список_фактических_параметров);
значением имя_указателя служит адрес функции, а с помощью операции разыменования * обеспечивается обращение по адресу к этой функции.
Арифметические операции над указателями на функции запрещены.
Указатели на функции в основном используются в следующих случаях.
- Многие библиотечные функции в качестве аргумента получают указатель на функцию. Например, функция сортировки qsort() получает четвертым аргументом указатель на составляемую пользователем функцию сравнения сортируемых элементов.
- Использование указателей на функции в качестве аргументов позволяет разрабатывать универсальные функции, реализующие известные алгоритмы или методы. Например, функции численного решения уравнений, интегрирования и дифференцирования.
- Указатели на функции могут использоваться для косвенного вызова резидентных программ, точка входа в которые записана в известное место памяти, например, по одному из неиспользуемых векторов прерываний.
В определении указателя на функцию тип возвращаемого значения, а также типы, количество, последовательность параметров должны совпадать с соответствующими типами и характеристиками параметров тех функций, адреса которых предполагается присваивать вводимому указателю при инициализации или с помощью оператора присваивания.
Пример 1.
//Определение и использование указателей на функции
#include "stdafx.h"
#include <iostream>
using namespace std;
//Определение и использование указателей на функции
void f1(); //объявление (прототип)функции f1
void f2(); //объявление (прототип)функции f2
int _tmain(int argc, _TCHAR* argv[]) {
void (*ptr)(); //ptr - указатель на функцию
f2(); //явный вызов функции f2
ptr=f2;//указателю присваивается адрес функции f2
(*ptr)();
//вызов функции f2 по ее адресу с разыменованием указателя
ptr=f1;//указателю присваивается адрес функции f1
(*ptr)();
//вызов функции f1 по ее адресу с разыменованием указателя
ptr(); // вызов функции f1 без разыменования указателя
system("pause");
return 0;
}
//описание функции f1 и f2
void f1() {
cout << "Выполняется f1\n";
}
void f2() {
cout << "Выполняется f2\n";
}Пример 2.
//Вариант 1 использования указателя на функцию
#include "stdafx.h"
#include <iostream>
using namespace std;
float plus(float, float); //Объявление (прототип) функции
int _tmain(int argc, _TCHAR* argv[]){
float x=2.1, y=4.89;
float (*func)(float,float);
//определение указателя func на функцию
printf("Сумма равна %.3f\n",plus(x,y));
func=plus;
//указателю присвоить адрес func точки входа в функцию plus
// Используем указатель на функцию
printf("Сумма = %.3f\n",func(x,y));
system("pause");
return 0;
}
//Описание функции сложения двух аргументов
float plus(float a, float b) {
return a+b;
}
//Вариант 2 использования указателя на функцию
#include "stdafx.h"
#include <iostream>
using namespace std;
float plus(float, float); //Объявление (прототип)функции
int _tmain(int argc, _TCHAR* argv[]){
float x=2.1, y=4.89;
float (*func)(float, float)=+
//определение указателя на функцию plus
printf("Сумма равна %.3f\n",plus(x,y));
//указателю присвоить адрес точки входа в функцию plus (Используем указатель на функцию)
printf("Сумма = %.3f\n",func(x,y));
system("pause");
return 0;
}
//Описание функции сложения двух аргументов
float plus(float a, float b) {
return a+b;
}