double arrow

Указатели на функции. Ссылка - это не особый тип данных, а "автоматически разыменуемый" указатель, т.е


Ссылка

Ссылка - это не особый тип данных, а "автоматически разыменуемый" указатель, т.е. это объект, который указывает на положение другой переменной.

Ссылка - это "неявный" указатель, который отличается от обычного "явного" указателя тем, что для ссылки не нужно специально записывать операцию разадресации (она подразумевается автоматически). Над указателями возможны арифметические операции. Над самой ссылкой арифметические операции невозможны (потому что они будут истолкованы компилятором как операции над тем объектом, на который ссылается ссылка).

Ссылка декларируется следующим образом:

type &ID = инициализатор;

Инициализатор - это идентификатор объекта, на который в дальнейшем будет указывать ссылка. Пример:

int a = 8;

int &r = a;

Ссылка стала "псевдонимом" объекта, указанного в качестве инициализатора. В данном примере, одинаковыми будут следующие действия:

a++;

r++;

Наиболее полезны ссылки оказываются в качестве параметров функций, т.к. значение (конкретный адрес) им тогда присваивается при вызове функции. Например, вышеприведенный пример с функцией zam тогда можно переписать так:




void zam(int &x, int &y)

{

int t = x;

x = y;

y = t;

}

Участок программы с обращением к данной функции:

void zam (int&, int&);

void main (void)

{

int a=2, b=3;

printf(" a = %d , b = %d\n", a, b);

zam (a, b);

printf(" a = %d , b = %d\n", a, b);

}

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

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

Рассмотрим методику работы с указателями на функции.

1. Как и любой объект языка Си, указатель на функции необходимо декларировать. Формат объявления указателя на функции следующий:

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

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

Например, объявление вида:

double (*p_f )(char, double);

говорит о том, что декларируется указатель p_f, который можно устанавливать на функции, возвращающие результат типа double и имеющие два параметра: первый – символьного типа, а второй – вещественного типа.

2. Идентификатор функции считается константным указателем, поэтому для того, чтобы установить переменную-указатель на конкретную функцию, достаточно ей присвоить ее идентификатор:



переменная-указатель = ID_функции;

Например, имеется функция с прототипом: double f1(char, double); тогда операция

p_f = f1;

установит указатель p_f на данную функцию.

Идентификатор функции может быть присвоен указателю и по-другому:

double f1(char C, double D){

... // тело функции f1

}

void FunOut(double (*p_f )(char, double)){

... // тело функции FunOut

}

void main(){

... // тело функции main

FunOut(f1);

... // тело функции main

}

Здесь при вызове функции FunOut в нее передается аргумент - указатель на функцию f1, который присваивается параметру p_f .

3. Вызов функции после установки на нее указателя выглядит так:

(*переменная-указатель)(список аргументов);

или

переменная-указатель (список аргументов);

После таких действий кроме стандартного обращения к функции:

ID_функции(список аргументов);

появляется еще два способа вызова функции:

(*переменная-указатель)(список аргументов);

или

переменная-указатель (список аргументов);

Последняя запись справедлива, так как p_f также является адресом начала функции в оперативной памяти.

Например, в теле вышеприведенной функции FunOut вызов функции по указателю может выглядеть так:

double zz=p_f('@', 3.14159);

В вышеприведенном примере тогда будет вызвана функция f1, причем C будет присвоено значение - символ @ , а D - 3.14159 .








Сейчас читают про: