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

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

 

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; //Все правильно

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

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

еще рефераты
Еще работы по информатике