Шаг 59.
Microsoft Visual C++ 2010. Язык С/С++.
Указатели и структуры данных. Указатели на функции

    На этом шаге мы рассмотрим особенности использования таких указателей.

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

  <Тип возвращаемого функцией значения> (*имя функции) (список параметров).

    Например:

  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. Результат работы приложения

    Со следующего шага мы начнем знакомиться со структурами.




Предыдущий шаг Содержание Следующий шаг