Глава 5 Указатели и ссылки Понятие указателя
Любой объект программы, будь то переменная базового или же производного типа, занимает в памяти определенную область. Местоположение объекта в памяти определяется его адресом. Как уже говорилось, при объявлении переменной для нее резервируется место в памяти, размер которого зависит от типа данной переменной, а для доступа к содержимому объекта служит его имя (идентификатор). Для того чтобы узнать адрес конкретной переменной, служит унарная операция взятия адреса. При этом перед именем переменной ставится знак амперсанда (&). Следующий ниже пример программы выведет на печать сначала значение переменной Varl и Var2, а затем ее адрес:
#include <iostream.h>
#define end1 '\n'
int main ()
{
unsigned int Varl = 40000;
unsigned int Var2 = 300;
cout « "Значение1: " « Varl « endl;
cout « "Адрес : " « &Varl « endl;
oout « П3начение2: " « Var2 « endl;
cout « "Адрес ; " « &Var2 « endl;
return 0;
}
В результате будет выведено:
Значение1: 40000 Адрес : Ox0068feOO
Значение2: 300
Адрес : Ox0068fdfc
Как видно из примера, адреса локальных переменных, размещаемых в стеке, следуют в обратном порядке (стек растет в направлении младших адресов). Результат может отличаться даже при повторном запуске программы, так как невозможно предугадать, по какому адресу начнут размещаться переменные. Важно другое: разница в адресах первой и второй переменной всегда будет одинакова и при четырехбайтном представлении типа int составит 4 байта (см. рис. 5.1).
Рис. 5.1. Переменные в памяти
Мощным средством разработчика программного обеспечения на C++ является возможность осуществления непосредственного доступа к памяти. Для этой цели предусматривается специальный тип переменных - указатели.
Указатель (pointer) представляет собой переменную, значение которой является адресом ячейки памяти. Указатель может ссылаться на переменную (базового или производного типа) или функцию Наибольшая эффективность применения указателей в разработке приложений достигается при использовании их с массивами к символьными строками.
Объявление указателя имеет следующий синтаксис:
тип объекта* идентификатор;
Здесь тип_объехта определяет тип данных, на которые ссылается указатель с именем идентификатор. Символ 'звездочка' (*) сообщает компилятору, что объявленная переменная является указателем и не зависимо от того, сколько памяти требуется отвести под сам объект, для указателя резервируется два или четыре байта в зависимости от используемой модели памяти.
Рис. 5.2. Смысл указателя
Поскольку указатель представляет собой ссылку на некоторую область памяти, ему может быть присвоен только адрес некоторой переменной (или функции), а не само ее значение. В случае некорректного присвоения компилятор выдаст соответствующее сообщение об ошибке.
Рассмотрим пример объявления и инициализации указателя.
char Symbol = ' Y' ;
char *pSymbol = &Symbol;
long Capital = 304L;
long* pLong;
pLong = &Capital;
В приведенном фрагменте объявляется символьная переменпая Symbol и инициализируется значением 'Y', затем определяется указатель на символьный тип данных pSymbol, значение которого назначается равным адресу переменной Symbol. Вслед за этим объявляется переменная capital типа long и указатель на этот же тип pLong, после чего производится инициализация указателя адресом переменной Capital.