Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции за I семестр 2014 - суммарный текст / Лекции за I семестр 2014 - суммарный текст.doc
Скачиваний:
209
Добавлен:
17.03.2016
Размер:
1.36 Mб
Скачать

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);

}

При таком способе передачи данных в функцию, их значения будут изменены, т.е. на экран монитора будет выведено:

a = 2 , b=3

a = 3 , b=2

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

void f1(int, const double *);

Рекомендуется указывать const перед всеми параметрами - указателями, для которых в функции не предусмотрено изменение значений, на которые они ссылаются. Это облегчает, например, отладку программы, т.к. по заголовку функции видно, какие данные в функции изменяются, а какие нет.

17.8. Ссылка

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

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

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

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);

}

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

17.9. Указатели на функции

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

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

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

}