Урок 7.1.4. Операция косвенной адресации

7.1.4. Операция косвенной адресации

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

*<адресное_выражение>

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

int q,b,*pq;
q=5; pq=&q;
b=*pq;

то в результате его выполнения переменная b примет значение 5. В последнем операторе b=*pq; по адресу, записанному в указателе pq, извлекается значение переменной q, т,е. числo 5, и присваивается переменной b. В данном случае мы извлекли значение не прямым обращением к переменной путем использования ее имени – q, а косвенно, путем использования ее адреса, имеющегося в указателе рq.

Выражение *pq записано справа от знака присваивания и является правоопределенным (r-value, right value) вариантом этого выражения. Как в указатель pq попал адрес переменной q – понятно, в результате выполнения предыдущего оператора рq=&q;.

Таким образом, в этом контексте операция косвенной адресации трактуется как "обратиться к данному по адресу, извлечь данное по адресу", и ее значением является данное, размещенное по этому адресу. Но как же определяется, сколько байтов данного нужно извлечь из адреса? Очень просто. К моменту использования указателя его тип всегда должен быть определен, в данном случае он имеет тип int и, следовательно, нужно извлечь два байта данного. Рассмотрим другой, несколько видоизмененный пример:

int q,b,*pb;
q=5; pb=&b;
*pb=q;

в котором операция косвенной адресации использована слева от операции присваивания.

Это случай так называемого левоопределенного выражения (l-value, left value) вида: *<адресное_выражение>. Теперь левосторонняя операция косвенной адресации с учетом операции присваивания трактуется как "записать данное по адресу", и в результате выполнения этого фрагмента программы переменная b примет значение 5, как и в предыдущем случае.

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

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

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

Тип объекта не может быть типом void – пустым типом, но значение объекта может быть "пустым", т.е. еще не известным, если ему присваивается значение с использованием левосторонней операции косвенной адресации. Мы уже приводили пример описания указателя на данные, тип которых заранее не определен: void *p5;

Такой указатель совместим с указателем на любой тип данных, т.е. ему можно присвоить адрес объекта любого типа, но перед использованием указателя, объявленного как void, он обязательно должен быть специфицирован типом объекта, на который он указывает, например:

void *p5;
double r,q;
q=1.85e-12;
p5=&q;
r=*((double *)p5);

Здесь использована операция преобразования типа (double *), с тем чтобы указатель на неопределенный тип данных р5 был преобразован к указателю на тип данных double, потому что операцией косвенной адресации мы желаем получить доступ к данному именно этого типа.
Было бы ошибкой записать последний оператор примера как r=*((double)p5);, ибо в этом случае указатель р5 приводился бы к числу с плавающей точкой типа double, а не к указателю на тип double.

Применение указателей, операций взятия адреса и косвенной адресации в программах на Си весьма обширно. Очень часто их применяют при передаче параметров в функции, когда необходимо передать не значения, а их адреса, при работе с массивами и т.д. Все это и многое другое будет рассмотрено далее.

рассказать друзьям и получить подарок

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов