Урок 18. Действия с указателями


Доступ к данным по указателю

После того как связали переменную и указатель, наша задача - использовать эту связку в своих целях, т.е. получить данные через указатель. Эту операцию делает возможной знакомая звездочка. На самом деле «звездочка» *, присутствующая в записи имени указателя - это оператор косвенного доступа к переменной, то есть через указатель. Примененный к указателю, он выдает значение переменной, на которую данный указатель указывает.
Например:

int *p; // Объявлен указатель на переменную целого типа
int i=1;
p = &i; // теперь p указывает на i
*p = *p+2; /* Здесь косвенный доступ к переменной i,
которая теперь равна 3 */

Другое название косвенного доступа – операция разыменования.

Когда использовать звездочку

Как вы могли заметить в предыдущем примере, звездочка перед именем указателя появляется не всегда. То есть, переменную-указатель можно в программе использовать разными способами
Эти отличия надо себе четко представлять. Почему, например, используя данные предыдущего примера, нельзя записать присваивание:

p = i;

Дело в том, что ячейка p может хранить только адрес, или, точнее, данные типа "адрес", а ячейка i - данные целого типа. Налицо несоответствие типов слева и справа от присваивания.
А если в теле программы (но не в описании!) перед p стоит звездочка, то тем самым мы указатель вместе со звездочкой превращаем в переменную целого (в нашем примере) типа. Таким образом, присваивание, например:

*p = 8;

совершенно корректно.
Кроме того, становится очевидным, что звездочка в описании (первая строка кода) и дальше в теле программы имеет как бы противоположный смысл: в первом случае мы говорим, что ячейка p будет хранить адрес, а во втором случае звездочка превращает ячейку-адрес в переменную.

Нулевой адрес

Для указателей, которые не хранят ни­каких адресов, введена константа «нулевой адрес», с именем NULL.

int *p;
p = NULL;

Эта константа может быть присвоена указателю на переменную любого типа. Нулевой адрес можно использовать чтобы "разорвать связь":

int i=1, *p; p=&i Получили связку "указатель-переменная"
*p = *p + 2; Получили косвенный доступ к переменной i: через указатель содержимое этой переменной увеличили на 2.
p = NULL; После выполнения операции p=NULL связь разрушится, но значение переменной i не изменится

Как использовать указатели

Поскольку результатом операции косвенного доступа является значение переменной, на которую указывает указатель, то запись *p (вместе звездочка и имя указателя) можно рассматривать как привычную переменную целого типа и выполнять с ней все арифметические и прочие операции, например:

*p = sqrt(*p+2);
printf("%d", *p);

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

int a=1; // переменной целого типа присвоена 1
int *pa,*pb; // объявлены два указателя на переменную целого типа
pa=&a; // первый указатель получил адрес переменной
pb=pa; // второй указатель теперь тоже хранит адрес этой же переменной
printf("%d", *pb); // здесь доступ к переменной "а" по указателю



На картинке это выглядит так:

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

float x,y,*ptr;

Два оператора присваивания

ptr=&x;
y=*ptr;

выполняют то же самое, что и один оператор присваивания y=x.

Указатели широко используются программистами-профессионалами. Язык Си позволяет резервировать любой "кусок" памяти (в байтах), возвращая адрес, который можно хранить в указателе. Этот процесс известен как динамическое резервирование памяти. С его помощью программа может использовать всю имеющуюся на компьютере память.

Вопросы для самопроверки

1. В каких операциях в программе указатель используется без звездочки и когда со звездочкой?
2. Что такое операция разыменования?
3. Что обозначает константа с именем NULL?
4. Как разорвать связь между указателем и переменной, на которую он указывает?
5. Как добиться того, чтобы два указателя указывали на одну и ту же ячейку-переменную?
6. Как через указатель выполнить присваивание значения одной переменной другой?

 









Последнее изменение этой страницы: 2016-04-07; Нарушение авторского права страницы

infopedia.su не принадлежат авторские права, размещенных материалов. Все права принадлежать их авторам. Обратная связь