Такие массивы по смыслу ничем не отличаются от массивов других объектов, однако форма их определения несколько необычна:
тип (*имя массива [размер]) (спецификация_параметров);
где тип определяет тип возвращаемых функциями значений;
имя_массива - произвольный идентификатор;
размер - количество элементов в* массиве;
спецификация_параметров - определяет состав и типы параметров функций. Пример:
int (*parray [4]) (char);
где parray - массив указателей на функции, каждому из которых можно присвоить адрес определенной выше функции int fic (char) и адрес любой функции с прототипом вида:
int имя_функции (char);
Массив в соответствии с синтаксисом языка является производным типом наряду с указателями и функциями. Массив функций создать нельзя, однако, как мы показали, можно определить массив указателей на функции. Тем самым появляется возможность создавать "таблицы переходов" (jump tables), или "таблицы передачи управления". С помощью таблицы переходов удобно организовывать ветвления с возвратом по результатам анализа некоторых условий. Для этого все ветви обработки (например, N+1 штук) оформляются в виде однотипных функций (с одинаковым типом возвращаемого значения и одинаковой спецификацией параметров). Определяется массив указателей из N+1 элементов, каждому элементу которого присваивается адрес конкретной функции обработки. Затем формируются условия, на основе которых должна выбираться та или иная функция (ветвь) обработки. Вводится индекс, значение которого должно находиться в пределах от 0 до N включительно, где (N+1) - количество ветвей обработки. Каждому условию ставится в соответствие конкретное значение индекса. По конкретному значению индекса выполняются обращение к элементу массива указателей на функции и вызов соответствующей функции обработки:
|
|
имя массива [индекс] (список_фактических_параметров);
(*имя массива [индекс]) (список_фактических_параметров);
Описанную схему использования массивов указателей на функции удобно применять для организации меню, точнее, программ, которыми управляет пользователь с помощью меню.
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "locale.h"
#include "stdlib.h"
#define N 2
void act0(char * name)
{
printf("%s: Работа завершена!\n",name);
_getch();
exit(0);
}
void act1(char * name)
{
printf("%s: работа l\n",name);
}
void act2(char * name)
{
printf("%s: работа 2\n",name);
}
int _tmain(int argc, _TCHAR* argv[])
{
/* Массив указателей на функции: */
setlocale(LC_ALL,"Russian");
void (*pact[])(char *)={act0,act1,act2};
char string[12];
int number;
printf("\n\nВводите имя: ");
scanf("%s",string);
printf("Вводите номера работ от 0 до %d:\n",N);
while (1)
{
scanf("%d",&number);
|
|
/* Ветвление по условию */
pact[number](string);
}
_getch();
return 0;
}
Пример выполнения программы:
Вводите имя: Peter
Вводите номера работы от 0 до 2:
Peter: работа 1
Peter: работа 1
Peter: работа 2
Peter: Работа Завершена!
В программе для упрощения нет защиты от неверно введенных данных, т.е. возможен выход индекса за пределы, определенные для массива pact[ ] указателей на функции. При такой ситуации результат непредсказуем.