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

Присваивание значений с помощью указателей

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

*р = 101;

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

(*р)++;

Круглые скобки здесь обязательны, поскольку оператор "*" имеет более низкий приоритет, чем оператор "++".

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

#include <iostream>

using namespace std;

int main()

{

 int *p, num;

 p = #

 *p = 100;

 cout << num << ' ';

 (*p)++;

 cout << num << ' ';

 (*p)--;

 cout << num << '\n';

 return 0;

}

Вот такие результаты генерирует эта программа.

100 101 100

Использование указателей в выражениях

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

Арифметические операции над указателями

С указателями можно использовать только четыре арифметических оператора: ++, --, + и -. Чтобы лучше понять, что происходит при выполнении арифметических действий с указателями, начнем с примера. Пусть p1 — указатель на int-переменную с текущим значением 2 ООО (т.е. p1 содержит адрес 2 ООО). После выполнения (в 32-разрядной среде) выражения

p1++;

содержимое переменной-указателя p1 станет равным 2 004, а не 2 001! Дело в том, что при каждом инкрементировании указатель p1 будет указывать на следующее int-значение. Для операции декрементирования справедливо обратное утверждение, т.е. при каждом декрементировании значение p1 будет уменьшаться на 4. Например, после выполнения инструкции

p1--;

указатель p1 будет иметь значение 1 996, если до этого оно было равно 2 000. Итак, каждый раз, когда указатель инкрементируется, он будет указывать на область памяти, содержащую следующий элемент базового типа этого указателя. А при каждом декрементировании он будет указывать на область памяти, содержащую предыдущий элемент базового типа этого указателя.

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

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

p1 = p1 + 9;

заставляет p1 ссылаться на девятый элемент базового типа указателя p1 относительно элемента, на который p1 ссылался до выполнения этой инструкций.

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

Помимо сложения указателя с целочисленным значением и вычитания его из указателя, а также вычисления разности двух указателей, над указателями никакие другие арифметические операции не выполняются. Например, с указателями нельзя складывать float- или double-значения.

Чтобы понять, как формируется результат выполнения арифметических операций над указателями, выполним следующую короткую программу. Она выводит реальные физические адреса, которые содержат указатель на int-значение (i) и указатель на float-значение (f). Обратите внимание на каждое изменение адреса (зависящее от базового типа указателя), которое происходит при повторении цикла. (Для большинства 32-разрядных компиляторов значение i будет увеличиваться на 4, а значение f — на 8.) Отметьте также, что при использовании указателя в cout-инструкции его адрес автоматически отображается в формате адресации, применяемом для текущего процессора и среды выполнения.

// Демонстрация арифметических операций над указателями.

#include <iostream>

using namespace std;

int main()

{

 int *i, j[10];

 double *f, g[10];

 int x;

 i = j;

 f = g;

 for(x=0; x<10; x++)

  cout << i+x << ' ' << f+x << '\n';

 return 0;

}

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

0012FE5C 0012FE84

0012FE60 0012FE8C

0012FE64 0012FE94

0012FE68 0012FE9C

0012FE6C 0012FEA4

0012FE70 0012FEAC

0012FE74 0012FEB4

0012FE78 0012FEBC

0012FE7C 0012FEC4

0012FE80 0012FECC

Узелок на память. Все арифметические операции над указателями выполняются относительно базового типа указателя.

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