Указатели в C++

Указатели широко используются в C++. В чем то, именно их наличие сделало этот язык более удобным для системного программирования. Но стоит отметить, что это одна из наиболее сложных для освоения возможностей C++. Идея работы с указателями состоит в том, что пользователь работает с адресом ячейки памяти и имеет возможность динамически создавать и уничтожать переменные.


Как правило, при обработке оператора объявления переменной тип имя_переменной; компилятор автоматически выделяет память под переменную имя_переменной в соответствии с указаннымтипом:

Доступ к объявленной переменной осуществляется по ее имени. При этом все обращения к переменной меняются на адрес ячейки памяти, в которой хранится ее значение:

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

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

Указатель — это переменная, значением которой является адрес памяти, по которому хранится объект определенного типа (другая переменная). Например, если Cэто переменная типа char, а P — указатель на C, значит в P находится адрес, по которому в памяти компьютера хранится значение переменной C.

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

тип имя_переменной;

Например:

Звездочка в описании указателя относится непосредственно к имени, поэтому, чтобы объявить несколько указателей, ее ставят перед именем каждого из них:

Операции * и & при работе с указателями

Операция получения адреса обозначается знаком &, а операция разадресации *. Первая возвращает адрес своего операнда. Например:

Операция разадресации * возвращает значение переменной, хранящееся в по заданному адресу, то есть выполняет действие, обратное операции &:

Присваивание указателей

Значение одного указателя можно присвоить другому. Если указатели одного типа, то для этого применяют обычную операцию присваивания . Рассмотрим ее на примере:

В данной программе определены: вещественная переменная PI=3.14159 и два указателя на тип float p1 и p2. В указатели записывается адрес переменной PI. В результате работы программы в переменных p1 и p2 будет хранится значение одного и того же адреса, по которому хранится вещественная переменная PI=3.14159.

Результат работы программы:

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

Без преобразования можно присваивать любому указателю указатель void*. Рассмотрим пример работы с указателями различных типов:

В указателях p1 и p2 хранится один и тот же адрес, но значения, на которые они ссылаются, оказываются разными. Это связано с тем, что указатель типа *float адресует 4 байта, а указатель *double — 8 байт. После присваивания p2=(double *)p1; при обращении к *p2 происходит следующее: к переменной, хранящийся по адресу p1, дописывается еще 4 следующих байт из памяти. В результате значение *p2 не совпадает со значением *p1. Результат работы программы будет примерно такой:

А вот что произойдет в результате работы следующего кода:

После присваивания p2=(double*)p1; при обращении к *p2 происходит следующее: из переменной, хранящийся по адресу p1, выделяется только 4 байта. В результате значение *p2 не совпадает со значением *p1.

Результат работы программы:

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


Похожие записи:

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля отмечены *