Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Konspekt_S__Chast_2.doc
Скачиваний:
31
Добавлен:
09.02.2015
Размер:
1 Mб
Скачать

Работа с указателями

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

int A = 2351, *p1;

double B = 3.14, *p2;

p1 = &A; // Указателю p1 присваивается адрес переменной А

p2 = &B; // Указателю p2 присваивается адрес переменной В

cout << “Значение переменной А: ” << A << endl;

cout << “Адрес переменной А: ” << p1 << endl;

cout << “Значение переменной В: ” << В << endl;

cout << “Адрес переменной В: ” << p2 << endl;

Результат выполнения этого фрагмента программы будет таким же, как и раньше.

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

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

int A = 2351, *p1;

double B = 3.14, *p2;

p1 = &A; // Указателю p1 присваивается адрес переменной А

p2 = &B; // Указателю p2 присваивается адрес переменной В

cout << “Значение переменной А: ” << *p1 << endl;

cout << “Адрес переменной А: ” << p1 << endl;

cout << “Значение переменной В: ” << *p2 << endl;

cout << “Адрес переменной В: ” << p2 << endl;

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

Обращение к указателю с помощью оператора * (например, *p1) означает следующее: взять из памяти по адресу, хранящемуся в указателе (p1 равно 101), столько байт памяти, сколько требуется базовому типу указателя (в данном случае базовый тип указателяint, следовательно – взять 4 байта) и работать с этими байтами, как со значением базового типа указателя (в нашем примере это значение 2351 типаint). Таким образом,*p1– это (в нашем примере) обычное значение типаintи с ним можно работать как с обычным целым числом.

С помощью указателей можно не только получать значения, расположенные по адресам, хранящимся в указателях, но и записывать нужные значения по этим адресам. Например: выполнение инструкции

*p1 = 4211;

приведет к тому, что переменная A, на которую ссылается указательp1, станет равна 4211, а не 2351.

Указатели могут использоваться в различных выражениях наравне с обычными переменными и константами:

B = (*p1 – 1000) * 2;// ПеременнаяВстанет равна значению (4211 - 1000) * 2 = 6422.0

Или так:

*p2 =(*p1 – 1000) * 2;// ПеременнаяBтакже будет равна значению 6422.0

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

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

int A = 5, B = 10, *p1 = &A, *p2 = &B;

double D = 3.14, *d = &D;

Здесь указатели p1 и p2 указывают на переменныеAиB соответственно. Указательd– на переменнуюD.

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

p1 = p2;// Теперь оба указателяp1 и p2ссылаются на переменнуюB

d = p1;// Ошибка – базовые типы не совпадают

Последней ошибки можно было бы избежать с помощью явного преобразования типов, например, так:

d = (double *) p1;

Но теперь указатель d будет содержать адрес переменнойB типаint, а попытка взять значение по этому адресу через указательd приведет к тому, что с этого адреса будут взяты не 4, а 8 байт памяти и полученное значение*d типаdoubleбудет непредсказуемым. Еще более неприятная ситуация может возникнуть, если попытаться записать данные по указателюd. Такая попытка может завершиться тем, что будут изменены данные, расположенные за переменнойB, а это приведет к неправильной работе программы. Обнаружить такие ошибки бывает очень сложно.

Явное преобразование указателей нежелательно. Но если это необходимо, то делать это надо очень аккуратно.

Хотя формально указатели представляют собой целые значения, присваивать им произвольные целые значения нельзя. Например, попытка присвоить указателю p1 значение 10000 (p1 = 10000;) приведет к возникновению ошибки на этапе компиляции программы. Единственным исключением является присвоение указателю нулевого значения:

p1 = 10000; // Ошибка

p1 = 0; // Все правильно

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

Указатели можно сравнивать с помощью операций отношения ==,!=,>,<. С помощью таких сравнений можно характеризовать взаимное расположение объектов, на которые ссылаются сравниваемые указатели, в памяти. Но сравнение указателей с помощью операций>,< имеет смысл только в том случае, если сравниваемые указатели содержат адреса связанных между собой переменных (например, элементов массива).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]