На этом шаге мы рассмотрим особенности использования таких указателей.
В языке С возможно определять указатели на функции и, следовательно, обрабатывать указатели, передавать их в качестве аргумента другим функциям и т. д. При объявлении указатель на функцию записывается в виде:
<Тип возвращаемого функцией значения> (*имя функции) (список параметров).
Например:
int (*comp)(char s1, char s2);
Это указатель на функцию comp (s1, s2), которая возвращает результат типа int. Если мы подействуем операцией разыменования (*) на этот указатель (по определению указателя записав воздействие в виде (*comp) (s1,s2)), то функция comp (s1, s2) выполнится и возвратит некое целое число.
Ранее мы видели, что имена массивов можно передавать в качестве аргументов функции. Теперь, поскольку есть указатели на функции, функции можно предавать в качестве аргументов другим функциям. В таких функциях их аргументы-функции описываются как указатели на функции, а передача функций в качестве аргументов происходит указанием имени самой функции. Все остальное улаживает компилятор. То есть с функциями, при передаче их в качестве аргументов другим функциям, происходит то же, что и с массивами: их имена считаются внешними переменными. Приведем пример функции gener(), которая имеет своими параметрами две функции: ввод строки символов и подсчета количества ненулевых битов в целом числе.
// 59_1.cpp: главный файл проекта. #include "stdafx.h" #include <clocale> //обязательно для функции setlocale() using namespace System; #include <stdio.h> //for getchar(),putchar() #include <conio.h> #include <stdlib.h> //for atoi() #define eof '?' #define MAXLINE 1000 //--- Функция подсчета количества битов в целом числе --- int bitcount(unsigned int n) { int b; for(b=0; n != 0; n>>=1) if(n & 01) //01-восьмеричная единица b++; return b; } //--- Ввод строки с клавиатуры --- int getline(char s[],int lim) { int c,i; for(i=0; i<lim-1 && (c=getchar()) != eof && c != '\n'; i++) s[i] = c; s[i] = '\0'; i++; //для учета количества return i; } //--- Функция вводит число n с клавиатуры и подсчитывает //количество двоичных единиц в нем --- int gener(int (*getline)(char s[],int lim),int (*bitcount) (unsigned int n)) { char s[MAXLINE]; int lim = 100; printf("Задайте число >\n"); (*getline)(s,lim); unsigned int n = atoi(s); n = (*bitcount)(n); return n; } void main() { setlocale(LC_ALL,"Russian"); //функция setlocale() с аргументами //для корректного вывода кириллицы int n=gener (getline,bitcount); printf("Количество двоичных единиц во введенном числе n = %o\n", n); _getch(); }
Мы уже знакомы с функциями getline() и bitcount() (последнюю составляли, когда изучали операции сдвига - она подсчитывает в целом без знака количество единиц (ненулевых битов), 42 шаг).
Рассмотрим вызывающую функцию gener(). Мы видим, что оба ее аргумента описаны как указатели на функции: первый - на функцию getline(), второй - на bitcount(). Затем идет выполнение первой переданной в качестве аргумента функции. Чтобы заставить выполниться функцию, находящуюся по адресу, который содержится в указателе getline, надо подействовать на него операцией разыменования (по определению указателя).
Получим (*getline)(s, lim);
Функция getline() выполнится и результатом ее работы станет введенное в строку s число, которое переводится в беззнаковое n с помошью функции atoi(). После этого выполнится функция bitcount(), тоже описанная как указатель. Результат ее работы и возвращается в качестве результата фуункции gener(). Результат расчета показан на рисунке 1.
Рис.1. Результат работы приложения
Со следующего шага мы начнем знакомиться со структурами.