Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика 1 курс / метод указания / Информатика. Основы программирования на С++. Учебное пособие.doc
Скачиваний:
142
Добавлен:
08.06.2015
Размер:
2.15 Mб
Скачать

7. Программирование с использованием указателей

Указатель– это именованная переменная, представляющая собой символический адрес, по которому располагается объект определенного типа. С помощью этой переменной организуется косвенный способ адресации.

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

7.1. Общие сведения об указателях

Объявление указателя имеет следующий вид:

type *ptr;

где ptrуказатель на значение типаtype;

* - символ унарной операции косвенной адресации.

Например:

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

float*a; //а – указатель на вещественное число типаfloat

void*p; //p– указатель на типvoid(бестиповый указатель)

Указатель инициализируется либо непосредственно при объявлении (для надежности), либо после объявления с помощью оператора присваивания. При этом ему присваивается конкретный или нулевой адрес.

Например:

intx,y=5;

int*yptr, *count=NULL; //указателю count присваивается нулевой адрес

int*xptr=&x; //указателю хptr присваивается адрес переменной х

. . . . . . . . . . .

yptr=&y; //указателю yptr присваивается адрес переменной y

Здесь &- символ унарной операции взятия адреса;NULL– символическая константа, равная нулевому адресу, по которому никогда не располагаются данные (этот адрес зарезервирован операционной системой для своих нужд).

Для того чтобы использовать значение, на которое указывает указатель, необходимо применить к указателю унарную операцию разыменования* (обращения по адресу).

Например:

x=*yptr; //присваивание числа y=5, находящегося по адресу yptr

Этот же результат можно получить, записав

x=y; //обычное присваивание без применения указателя

или

*xptr=*yptr; //по адресуxptrпомещается значение,

//расположенное по адресу yptr

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

Например:

float*d,c=2;void*q;

q=d; //указательqиd- синонимы указывают на типfloat

*q=c; //по адресуqпомещается значениестипаfloat

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

Например:

yptr=&x; //yptrбудет указывать на х

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

Например:

cout<<&yptr; //печать адреса указателяyptr

Можно так же определить указатель на указатель и так далее сколько нужно раз.

Например:

intz=37;

int*pz=&z; //pz– указатель наz

int**ppz=&pz; //ppz– указатель на указательpz

В данном случае при вызове **ppzпоследовательно обеспечивается доступ к участку памяти *ppz= =pz, затем *pz= =z, т.е. **ppzдает значение 37.

С указателями можно выполнять не только операции присваивания и обращения по адресу, но и ряд других операций:

  • унарные операции ++,--;

  • аддитивные и составные операции с целыми числами +, -, +=, -=;

  • вычитание указателей (сложение указателей запрещено);

  • операции отношения.

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

Массивыи указатели в С++ тесно связаны и могут быть использованы практически эквивалентно. Имя массива можно понимать какконстантный указательна первый элемент массива. Его отличие от обычного указателя в том, что его нельзя модифицировать. Однако константный указатель можно присваивать переменной типа указатель.

Например:

intb[5], *pt;

pt=b; //эта запись эквивалентнаpt=&b[0]

После инициализации указателя его можно использовать для ссылок на элементы массива b[i]с помощью записи*(pt+i).Указатели можно индексировать точно так же, как и массивы. Например, выражениеpt[i] ссылается на элемент массиваb[i].Учитывая, чтоb=&b[0], в целом можно считать, чтоb[i] – индексированный указатель. Эта взаимосвязь отражена графическина рис. 7.1.

Рис. 7.1. Взаимосвязь указателя с одномерным массивом

Двумерные массивы заданной размерности располагаются в памяти подобно одномерным массивам, занимая построчно смежные ячейки. Поэтому для работы с таким массивом достаточно одного указателя.

Например:

floatmas[4] [2], *ptr;

ptr=mas; //или ptr=& mas[0] [0]

На рис. 7.2 представлена схема расположения массива masв памяти компьютера.

Рис. 7.2. Взаимосвязь указателя и двумерного массива

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

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