Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lekcii_1_10 / Лекция 06.docx
Скачиваний:
48
Добавлен:
21.05.2015
Размер:
475.25 Кб
Скачать

Указатели

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

При рассмотрении темы указателей нам придется использовать такие понятия, как размер базовых С++-типов данных. В этой главе мы предположим, что символы занимают в памяти один байт, целочисленные значения — четыре, значения с плавающей точкой типа float — четыре, а значения с плавающей точкой типа double — восемь (эти размеры характерны для типичной 32-разрядной среды).

Что представляют собой указатели

Указатели — это переменные, которые хранят адреса памяти. Чаще всего эти адреса обозначают местоположение в памяти других переменных. Например, если х содержит адрес переменной у, то о переменной, х говорят, что она "указывает" на у.

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

Переменные-указатели (или переменные типа указатель) должны быть соответственно объявлены. Формат объявления переменной-указателя таков:

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

Здесь элемент тип означает базовый тип указателя, причем он должен быть допустимым С++-типом. Элемент имя_переменной представляет собой имя переменной-указателя. Рассмотрим пример. Чтобы объявить переменную р указателем на int-значение, используйте следующую инструкцию.

int *р;

Для объявления указателя на float-значение используйте такую инструкцию.

float *р;

В общем случае использование символа "звездочка" (*) перед именем переменной в инструкции объявления превращает эту переменную в указатель.

Базовый тип указателя определяет тип данных, на которые он будет ссылаться.

Тип данных, на которые будет ссылаться указатель, определяется его базовым типом. Рассмотрим еще один пример.

int *ip; // указатель на целочисленное значение

double *dp; // указатель на значение типа double

Как отмечено в комментариях, переменная ip — это указатель на int-значение, поскольку его базовым типом является тип int, а переменная dp — указатель на double-значение, поскольку его базовым типом является тип double, Следовательно, в предыдущих примерах переменную ip можно использовать для указания на int-значения, а переменную dp на double-значения. Однако помните: не существует реального средства, которое могло бы помешать указателю ссылаться на "бог-знает-что". Вот потому-то указатели потенциально опасны.

Операторы, используемые с указателями

С указателями используются два оператора: "*" и "&" Оператор "&" — унарный. Он возвращает адрес памяти, по которому расположен его операнд.

Например, при выполнении следующего фрагмента кода

balptr = &balance;

в переменную balptr помещается адрес переменной balance. Этот адрес соответствует области во внутренней памяти компьютера, которая принадлежит переменной balance. Выполнение этой инструкции никак не повлияло на значение переменной balance. Назначение оператора можно "перевести" на русский язык как "адрес переменной", перед которой он стоит. Следовательно, приведенную выше инструкцию присваивания можно выразить так: "переменная balptr получает адрес переменной balance". Чтобы лучше понять суть этого присваивания, предположим, что переменная balance расположена в области памяти с адресом 100. Следовательно, после выполнения этой инструкции переменная balptr получит значение 100.

Второй оператор работы с указателями (*) служит дополнением к первому (&). Это также унарный оператор, но он обращается к значению переменной, расположенной по адресу, заданному его операндом. Другими словами, он ссылается на значение переменной, адресуемой заданным указателем. Если (продолжая работу с предыдущей инструкцией присваивания) переменная balptr содержит адрес переменной balance, то при выполнении инструкции

value = *balptr;

переменной value будет присвоено значение переменной balance, на которую указывает переменная balptr. Например, если переменная balance содержит значение 3200, после выполнения последней инструкции переменная value будет содержать значение 3200, поскольку это как раз то значение, которое хранится по адресу 100. Назначение оператора "*" можно выразить словосочетаинем "по адресу". В данном случае предыдущую инструкцию можно прочитать так: "переменная value получает значение (расположенное) по адресу balptr". Действие приведенных выше двух инструкций схематично показано на рис. 6.1.

Последовательность операций, отображенных на рис. 6.1, реализуется в следующей программе.

#include <iostream>

using namespace std;

int main()

{

 int balance;

 int *balptr;

 int value;

 balance = 3200;

 balptr = &balance;

 value = *balptr;

 cout << "Баланс равен:" << value <<'\n';

 return 0;

}

При выполнении этой программы получаем такие результаты:

Баланс равен: 3200

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

Операция непрямого доступаэто процесс использования указателя для доступа к некоторому объекту.

Соседние файлы в папке lekcii_1_10