Назад | Начало урока | Вперед
Содержание

Глава 8

Указатели

Оператор обращения к адресу (&)

Оператор адреса и обращение к адресу локальной переменной

// Listing 8.1 Demonstrates address of operator
// and addresses of local variables


#include <iostream.h>

int main()

// using namespace std;

unsigned short shortVar = 5;
unsigned long longVar = 65535;
long sVar = -65535;

cout << "shortVar:\t" << shortVar;
cout << "\tAddress of shortVar:\t";
cout << &shortVar << "\n";

cout << "longVar:\t" << longVar;
cout << "\tAddress of longVar:\t" ;
cout << &longVar << "\n";

cout << "sVar:\t\t" << sVar;
cout << "\tAddress of sVar:\t" ;
cout << &sVar << "\n";

return 0;


Анализ:

Сначала в программе объявляются и инициализируются три переменные разных типов.

unsigned short shortVar=5;
unsigned long longVar=65535;
long sVar = -65535;

Затем выводятся значения переменных и адреса переменных

cout << "shortVar:\t" << shortVar;
cout << "\tAddress of shortVar:\t";
cout << &shortVar << "\n";

cout << "longVar:\t" << longVar;
cout << "\tAddress of longVar:\t" ;
cout << &longVar << "\n";

cout << "sVar:\t\t" << sVar;
cout << "\tAddress of sVar:\t" ;
cout << &sVar << "\n";

Результат выполнения програмы:

shortVar: 5 Address of shortVar: 0012FF7C
longVar: 65535 Address of longVar: 0012FF78
sVar: -65535 Address of sVar: 0012FF74

Вверх

Сохранение адреса в указателе

Каждая переменная имеет адрес. Даже не зная сам адрес(номер ячейки)
значение его можно сохранить в другой переменной. Такая переменная,
хранящая адрес другого объекта называется указателем (pointer).

Предположим что существует переменная howOld типа integer.
Чтобы объявить на нее указатель с именем pAge, можно написать:

int * pAge = 0;

Этой строкой переменная pAge объявляется указателем на тип int.
Это означает что pAge будет содержать адрес значения типа int.
Компилятор различает тип переменной, адрес которой будет храниться
в указателе. При несовпадении типов будет выдано сообщение об ошибке.

Следует отметить что pAge - обычная переменная. При объявлении переменной
целочисленного типа (например int) указывается что в ней будет
будет храниться целое число, и компилятор выделит под нее соответствующее
количество памяти.

Когда переменная объявляется указателем на какой-либо тип, то это значит
что она будет хранить адрес переменной определенного типа
(обычно
размер самого указателя 4 байта). Таким образом указатели являются просто
определенным типом переменных.

Вверх

Пустые и дикие указатели

В вышеуказанном примере переменная pAge инициализируется нулевым значением.
Указатели, значения которых равны 0 называются пустыми (null pointer).
После объявления указателю обязательно надо присвоить какое-либо
значение. Если заранее неизвестно какой адрес должен храниться в
указателе, ему присваивается значение 0.

Неинициализированные указатели называются дикими (wild pointer).
Они очень опасны.


Примечание: Не шутите с этим: Всегда инициализируйте указатели!

Присвоить адрес переменной howOld указателю pAge можно следующим
образом:

unsigned short int howOld = 50;
unsigned short int * pAge = 0;
pAge = &howOld;

Можно несколько сократить эту запись объединив две послдение
строки в одну:

unsigned short int howOld = 50;
unsigned short int * pAge = &howOld;

Теперь указатель pAge содержит адрес переменной howOld.
С помощью этого указателя можно получить и значение переменной,
на которую он указывает, в данном случае - 50.

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

Косвенное обращение подразумевает получение доступа к значению
переменной по адресу, содержащемуся в указателе.

Всегда инициализируйте указатели. Неинициализированные указатели называются
дикими. (wild pointer). Можно указатель инициализировать нулевым
значением. Такой указатель называется пустым (null pointer)


Примечание:

У обычной переменной тип в объявлении сообщает компилятору,
сколько памяти необходимо для размещения ее значения.
Тип указателя предназначен вовсе не для этого: размер всех
указателей - 4 байта. Тип указателя сообщает компилятору,
сколько памяти необходимо для объекта, адрес которого указатель
содержит!

Например:

unsigned short int * pAge = 0;

В этом объявлении указателя pAge на переменную типа
unsigned short int компилятору сообщается , что указатель
(которому нужно 4 байта для хранения адреса) будет содержать
адрес объекта типа unsigned short int, для хранения значения
которого достаточно двух байтов.


Вверх

Оператор косвенного доступа (*)
Оператор косвенного доступа (*) называется так же оператором
взятия значения, разыменования или ссылкой (dereference).
При извлечении значения из этого указателя будет возвращено
то значение, которое хранится по адресу, содержащемуся в указателе.

Нормальные переменные обладают прямым доступом к собственным
значениям. Если создать новую переменную типа unsigned short int
с именем yourAge и присвоить ей значение другой переменной, howOld,
то можно было бы написать:

unsigned short int yourAge;
yourAge = pAge;

Оператор косвенного доступа (*) перед переменной pAge означает,
что "Само значение находится по адресу..." или иными словами:
"Возьмите значениею. хранимое по адресу находящемуся в переменной pAge,
и присвойте его переменной yourAge ".


Примечание:

В указателях звездочка (*) используется двумя разными способами:

- при объявлении указателя,
- а так же в операторе косвенного доступа.

При объявлении указателя звездочка (*) является частью синтаксиса
и располагается после указания типа объекта.
Например:

unsigned short int * pAge = 0;

При ссылке на указатель, звездочка (оператор косвенного доступа
или взятия значения) означает что речь идет о значении в памяти,
находящемся по адресу в данной переменной. а не о самом адресе.

*pAge = 5;

Заметьте что тот же самый символ (*) ипользуется как оператор
умножения. Что именно имел в иду программист поставив звездочку,
компилятор определяет исходя из контекста.


Вверх

Указатели, адреса и переменные

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

Рассмотрим фрагмент кода:
int theVariable = 5;
int *pPointer = &theVariable;

В первой строке объявляется переменная целого типа theVariable,
которой присваивается значение 5. В следующей строке объявляется
указатель pPointer для типа int, которому присваивается адрес переменной
theVariable. Переменная pPointer является указателем и содержит адрес
переменной theVariable. Значение. хранящееся по адресу, записанному в
pPointer, равно 5.

Ниже на картинке схематически показана переменная theVariable
и указатель pPointer, содержащий ее адрес.


Назад | Начало урока | Вверх | Вперед
Содержание

Hosted by uCoz