Чтение онлайн

ЖАНРЫ

Язык Си - руководство для начинающих

Д. МАРТИН

Шрифт:

return(u);

и изменить форму вызова в функции main следующим образом:

х = interchange(x, у);

В результате такого обращения к функции переменная х получит новое значение, но у при этом не изменится.

С помощью оператора return в вызывающую программу можно передать только одну величину. Но нам нужно передать две величины. Это оказывается вполне осуществимым! Для этого нужно лишь воспользоваться "указателями".

Указатели:

первое знакомство

Указатели? Что это такое? Вообще говоря, указатель - некоторое символическое представление адреса. Например, ранее мы воспользовались операцией получения адреса для нахождения адреса переменной pooh. В данном случае &pooh означает "указатель на переменную pooh". Фактический адрес - это число (в нашем случае 56002), а символическое представление адреса &pooh является константой типа указатель. После всего сказанного выше становится очевидным, что адрес ячейки, отводимой переменной pooh, в процессе выполнения программы не меняется.

В языке Си имеются и переменные типа указатель. Точно так же как значением переменной типа char является символ, а значением переменной типа int– целое число, значением переменной типа указатель служит адрес некоторой величины. Если мы дадим указателю имя ptr, то сможем написать, например, такой оператор

ptr = &pooh; /* присваивает адрес pooh переменной ptr */

Мы говорим в этом случае, что ptr "указывает на" pooh. Различие между двумя формами записи: ptr и &pooh, заключается в том, что ptr– это переменная, в то время как &pooh– константа. В случае необходимости мы можем сделать так, чтобы переменная ptr указывала на какой-нибудь другой объект:

ptr = &bah; /* ptr указывает на bah, а не на pooh */

Теперь значением переменной ptr является адрес переменной bah.

Операция косвенной адресации: *

Предположим, мы знаем, что в переменной ptr содержится ссылка на переменную bah. Тогда для доступа к значению этой переменной можно воспользоваться операцией "косвенной адресации" (*). (Не путайте эту унарную операцию косвенной адресации с бинарной операцией умножения *).

val = *ptr; /* определение значения, на которое указывает ptr */

Последние два оператора, взятые вместе, эквивалентны следующему:

val = bah;

Использование операций получения адреса и косвенной адресации оказывается далеко не прямым путем к результату; отсюда и появление слова "косвенная" в названии операции.

Резюме: операции, связанные с указателями

I. Операция получения адреса &

Когда за этим знаком следует имя переменной, результатом операции является адрес указанной переменной.

Пример:

&nurse дает адрес переменной nurse.

II. Операция косвенной адресации

* Когда за этим таком следует

указатель на переменную, результатом операции является величнна, помещенная и ячейку с указанным адресом.

Пример:

nurse = 22;pir = &nurse; /* указатель на nurse */ val = *ptr;

Результатом выполнения этого фрагмента является присваивание значения 22 переменной val.

Описание указателей

Мы знаем, как описывать переменные типа int и других типов. Но как описать переменную типа "указатель"? На первый взгляд это можно сделать так:

pointer ptr; /* неправильный способ описания указателя */

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

int *pi; /* указатель на переменную типа целого */

char *рс; /* указатель на символьную переменную */

float *pf, *pg; /* указатели на переменные с плавающей точкой */

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

РИС. 9.5. Описание и использование указателей.

Точно так же величина (*рс), на которую ссылается переменна рс, имеет тип char. Что можно сказать о самой переменной рс? Мы считаем, что она имеет тип "указатель на переменную типа char". Ее величина, являющаяся адресом,- это целое число без знака, поэтому при выводе на печать значения переменной рс мы будем пользоваться форматом %u.

Использование указателей для связи между функциями

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

/* обмен3 */

main

{

int x = 5, у = 10;

printf(" Вначале x = %d и у = %d.\n" , x, у);

interchange(&x,&y); /* передача адресов функции */

printf(" Теперь x = %d и у = %d.\n", x, у);

}

interchange(u, v)

Поделиться с друзьями: