Опубликован: 02.02.2011 | Доступ: свободный | Студентов: 3387 / 991 | Оценка: 4.43 / 3.57 | Длительность: 33:06:00
Специальности: Программист
Лекция 6:

Тип указатель: указатели на функции

< Лекция 5 || Лекция 6: 123 || Лекция 7 >
Аннотация: В лекции рассматриваются определение указателя на функцию, способы объявления, адресуемость и обращение к функции через указатель, передачу фактических параметров указателю на функцию, использование указателя на функцию в качестве параметра функции.

Цель лекции: изучить указатели на функции и методы передачи функций как параметров, научиться использовать указатели на функции в программных кодах на языке 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; 
  //определение указателя на функцию 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;
}
< Лекция 5 || Лекция 6: 123 || Лекция 7 >
Денис Курбатов
Денис Курбатов
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!


( ! ) Warning: include_once(./includes/unicode.entities.inc) [<a href='function.include-once'>function.include-once</a>]: failed to open stream: No such file or directory in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9974105338160watchdog( )../bootstrap.inc:0
23.9977105340608module_invoke( )../bootstrap.inc:967
33.9977105342464call_user_func_array ( )../module.inc:462
43.9977105342800devel_watchdog( )../module.inc:462
53.9978105343648decode_entities( )../devel.module:382
63.9979105345568drupal_error_handler( )../devel.module:340
73.9979105349176watchdog( )../common.inc:663
83.9979105351224module_invoke( )../bootstrap.inc:967
93.9979105353080call_user_func_array ( )../module.inc:462
103.9979105353416devel_watchdog( )../module.inc:462
113.9980105354112decode_entities( )../devel.module:382

( ! ) Warning: include_once() [<a href='function.include'>function.include</a>]: Failed opening './includes/unicode.entities.inc' for inclusion (include_path='.:/usr/local/zend/var/libraries/Zend_Framework_1/default/library:/usr/local/zend/share/pear') in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9974105338160watchdog( )../bootstrap.inc:0
23.9977105340608module_invoke( )../bootstrap.inc:967
33.9977105342464call_user_func_array ( )../module.inc:462
43.9977105342800devel_watchdog( )../module.inc:462
53.9978105343648decode_entities( )../devel.module:382
63.9979105345568drupal_error_handler( )../devel.module:340
73.9979105349176watchdog( )../common.inc:663
83.9979105351224module_invoke( )../bootstrap.inc:967
93.9979105353080call_user_func_array ( )../module.inc:462
103.9979105353416devel_watchdog( )../module.inc:462
113.9980105354112decode_entities( )../devel.module:382

( ! ) Warning: include_once(./includes/unicode.entities.inc) [<a href='function.include-once'>function.include-once</a>]: failed to open stream: No such file or directory in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9974105338160watchdog( )../bootstrap.inc:0
23.9977105340608module_invoke( )../bootstrap.inc:967
33.9977105342464call_user_func_array ( )../module.inc:462
43.9977105342800devel_watchdog( )../module.inc:462
53.9978105343648decode_entities( )../devel.module:382
63.9985105345760drupal_error_handler( )../devel.module:340
73.9985105349448watchdog( )../common.inc:663
83.9986105351496module_invoke( )../bootstrap.inc:967
93.9986105353352call_user_func_array ( )../module.inc:462
103.9986105353688devel_watchdog( )../module.inc:462
113.9986105354464decode_entities( )../devel.module:382

( ! ) Warning: include_once() [<a href='function.include'>function.include</a>]: Failed opening './includes/unicode.entities.inc' for inclusion (include_path='.:/usr/local/zend/var/libraries/Zend_Framework_1/default/library:/usr/local/zend/share/pear') in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9974105338160watchdog( )../bootstrap.inc:0
23.9977105340608module_invoke( )../bootstrap.inc:967
33.9977105342464call_user_func_array ( )../module.inc:462
43.9977105342800devel_watchdog( )../module.inc:462
53.9978105343648decode_entities( )../devel.module:382
63.9985105345760drupal_error_handler( )../devel.module:340
73.9985105349448watchdog( )../common.inc:663
83.9986105351496module_invoke( )../bootstrap.inc:967
93.9986105353352call_user_func_array ( )../module.inc:462
103.9986105353688devel_watchdog( )../module.inc:462
113.9986105354464decode_entities( )../devel.module:382

( ! ) Warning: include_once(./includes/unicode.entities.inc) [<a href='function.include-once'>function.include-once</a>]: failed to open stream: No such file or directory in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9992105338704watchdog( )../bootstrap.inc:0
23.9992105340752module_invoke( )../bootstrap.inc:967
33.9992105342608call_user_func_array ( )../module.inc:462
43.9992105342944devel_watchdog( )../module.inc:462
53.9993105343648decode_entities( )../devel.module:382
63.9993105345568drupal_error_handler( )../devel.module:340
73.9993105349176watchdog( )../common.inc:663
83.9993105351224module_invoke( )../bootstrap.inc:967
93.9994105353080call_user_func_array ( )../module.inc:462
103.9994105353416devel_watchdog( )../module.inc:462
113.9994105354112decode_entities( )../devel.module:382

( ! ) Warning: include_once() [<a href='function.include'>function.include</a>]: Failed opening './includes/unicode.entities.inc' for inclusion (include_path='.:/usr/local/zend/var/libraries/Zend_Framework_1/default/library:/usr/local/zend/share/pear') in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9992105338704watchdog( )../bootstrap.inc:0
23.9992105340752module_invoke( )../bootstrap.inc:967
33.9992105342608call_user_func_array ( )../module.inc:462
43.9992105342944devel_watchdog( )../module.inc:462
53.9993105343648decode_entities( )../devel.module:382
63.9993105345568drupal_error_handler( )../devel.module:340
73.9993105349176watchdog( )../common.inc:663
83.9993105351224module_invoke( )../bootstrap.inc:967
93.9994105353080call_user_func_array ( )../module.inc:462
103.9994105353416devel_watchdog( )../module.inc:462
113.9994105354112decode_entities( )../devel.module:382

( ! ) Warning: include_once(./includes/unicode.entities.inc) [<a href='function.include-once'>function.include-once</a>]: failed to open stream: No such file or directory in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9992105338704watchdog( )../bootstrap.inc:0
23.9992105340752module_invoke( )../bootstrap.inc:967
33.9992105342608call_user_func_array ( )../module.inc:462
43.9992105342944devel_watchdog( )../module.inc:462
53.9993105343648decode_entities( )../devel.module:382
63.9998105345760drupal_error_handler( )../devel.module:340
73.9999105349448watchdog( )../common.inc:663
83.9999105351496module_invoke( )../bootstrap.inc:967
93.9999105353352call_user_func_array ( )../module.inc:462
103.9999105353688devel_watchdog( )../module.inc:462
113.9999105354464decode_entities( )../devel.module:382

( ! ) Warning: include_once() [<a href='function.include'>function.include</a>]: Failed opening './includes/unicode.entities.inc' for inclusion (include_path='.:/usr/local/zend/var/libraries/Zend_Framework_1/default/library:/usr/local/zend/share/pear') in /.2/var_www_new.intuit.ru/htdocs/includes/unicode.inc on line 340
Call Stack
#TimeMemoryFunctionLocation
13.9992105338704watchdog( )../bootstrap.inc:0
23.9992105340752module_invoke( )../bootstrap.inc:967
33.9992105342608call_user_func_array ( )../module.inc:462
43.9992105342944devel_watchdog( )../module.inc:462
53.9993105343648decode_entities( )../devel.module:382
63.9998105345760drupal_error_handler( )../devel.module:340
73.9999105349448watchdog( )../common.inc:663
83.9999105351496module_invoke( )../bootstrap.inc:967
93.9999105353352call_user_func_array ( )../module.inc:462
103.9999105353688devel_watchdog( )../module.inc:462
113.9999105354464decode_entities( )../devel.module:382