Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Реализация программы через указатели на функции

Читайте также:
  1. Begin {начало основной программы} . . .
  2. Begin {начало основной программы} . . .
  3. HR– менеджмент: технологии, функции и методы работы
  4. II Частные производные функции нескольких переменных
  5. II. Организация и программы Олимпийских игр.
  6. II. Требования к результатам освоения основной образовательной программы начального общего образования
  7. II. ТРЕБОВАНИЯ К РЕЗУЛЬТАТАМ ОСВОЕНИЯ ОСНОВНОЙ ОБРАЗОВАТЕЛЬНОЙ ПРОГРАММЫ НАЧАЛЬНОГО ОБЩЕГО ОБРАЗОВАНИЯ

 

Указатели на функции – это указатели, т.е. переменные, которые указывают на адрес функции. Запущенная программа получает определённую область в оперативной памяти. И исполняемый скомпилированный программный код, и используемые переменные, размещаются в этой памяти.

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

При использовании имени функции без последующих скобок и параметров имя функции выступает в качестве указателя на эту функцию, и его значением служит адрес размещения функции в памяти (как в случае с указателем на массив – имя массива является указателем на его первый элемент).

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

Указатель на функцию определяется следующим образом:

тип функции (*имя_указателя)(спецификация_параметров);

Например:

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 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Реализация программы обычным способом| Объявления в средствах массовой информации

mybiblioteka.su - 2015-2024 год. (0.01 сек.)