Операция взятия адреса

Операция разадресации

Адресные операции

Язык С++ поддерживает два адресных оператора: операция взятия адреса & и косвенная операция *. Эти операции используются для работы с переменными типа указатель.

УКАЗАТЕЛЬ - это переменная, содержащая адрес некоторых данных, а не их значение. Зачем это нужно?

Во-первых, мы можем использовать указатель места расположения различных данных и различных структур данных. Изменением адреса, содержащегося в указателе, вы можете манипулировать (создавать, считывать, изменять) информацию в различных ячейках. Это позволит вам, например, связать несколько зависимых структур данных с помощью одного указателя.

Во-вторых, использование указателей позволит вам создавать новые переменные в процессе выполнения программы. С++ позволяет вашей программе запрашивать некоторое количество памяти (в байтах), возвращая адреса, которые можно запомнить в указателе. Этот прием известен как ДИНАМИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ; используя его, ваша программа может приспосабливаться к любому объему памяти, в зависимости от того как много (или мало) памяти доступно вашему компьютеру.

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

Форма записи:

* Идентификатор

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

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

Рассмотрим типичные ситуации, когда указатель содержит недопустимый адрес:

• указатель является нулевым;

• указатель определяет адрес такого объекта, который не является активным в момент ссылки;

• указатель определяет адрес, который не выровнен до типа объекта, на который он указывает;

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

Форма записи:

& Идентификатор;

Операция адрес (&) дает адрес своего операнда: если sum есть переменная типа int, тогда &sum есть адрес /ячейка памяти/ этой переменной. Таким образом, если msg есть ссылка на переменную типа char, тогда *msg есть символ, на который указывает msg.

Операндом может быть любое именуемое выражение. Имя функции или массива также может быть операндом операции «адрес», хотя в этом случае знак операции является лишним, так как имена массивов и функций являются адресами. Результатом операции адрес является указатель на операнд. Тип, адресуемый указателем, является типом операнда.

Операция адрес не может применяться к элементам структуры, являющимися полями битов, и к объектам с классом памяти register.

Рассмотрим следующую программу:

void main()

{

int ivar,*iptr;

 

iptr = &ivar;

ivar = 421;

printf("Размещение ivar: %p ",&ivar);

printf("Содержимое ivar: %d ", ivar);

printf("Содержимое iptr: %p ", iptr);

printf("Адресуемое значение: %d ",*iptr);

}

 

В ней объявлены две переменные: ivar и iptr. Первая, ivar - это целая переменная, т.е. содержащая значение типа int. Вторая, iptr - это указатель на целую переменную, следовательно, она содержит АДРЕС значения типа int. Можно также сказать, что переменная iptr - это указатель, так как перед ее описанием стоит звездочка

В основном, данная программа делает следующее:

- адрес переменной ivar присваисвается iptr

- целое значение 421 присваивается ivar

Адресный оператор (&) позволяет получить адрес, по которому размещено значение переменной ivar.

Введя эту программу в свой компьютер и выполнив ее, вы получите следующий результат:

Размещение ivar: 166E

Содержимое ivar: 421

Содержимое iptr: 166E

Адресуемое значение: 421

 

Первые две строки указывают адрес и содержимое ivar. Третья представляет адрес, содержащийся в iptr. Как видите, это адрес переменной ivar, т.е. место в памяти, где ваша программа решила создать переменную с идентификатором ivar. В последней строке печатается то, что хранится по этому адресу - те же самые данные, которые уже присвоены переменной ivar.

Заметим, что в третьем обращении к функции printf используется выражение iptr, содержимое которого есть адрес ivar. В последнем обращении к printf используется выражение *iptr, которое позволяет получить данные, хранящиеся по этому адресу.

Рассмотрим теперь небольшую вариацию предыдущей программы:

void main()

{

int ivar,*iptr;

 

iptr = &ivar;

*iptr = 421;

printf("Размещение ivar: %p ",&ivar);

printf("Содержимое ivar: %d ", ivar);

printf("Содержимое iptr: %p ", iptr);

printf("Адресуемое значение: %d ",*iptr);

}

 

В этой программе также адрес переменной ivar присваивается iptr, но вместо присваивания числа 421 переменной ivar, это значение присваивается по указателю *iptr. Каков результат ? Точно такой же, как и в предыдущей программе. Почему ? Потому что выражения *iptr и ivar суть одна и та же ячейка памяти - поэтому в этом случае оба оператора заносят значение 421 в одну и ту же ячейку памяти.