Операторы косвенного обращения и взятия адреса

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

Результат выполнения оператора косвенного обращения представляет собой тип, если тип операнда — указатель на тип. Если операнд указывает на функцию, результатом является указатель функции. Если он указывает на объект, результатом является адресующее объект значение (lvalue).

Если значение указателя недопустимо, результат оператора косвенного обращения не будет определен. Некоторые типичные условия, при которых значение указателя становится недопустимым.

  • Указатель является пустым указателем.

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

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

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

Унарный оператор взятия адреса ( & ) предоставляет адрес своего операнда. Операнд должен представлять:

  • Значение lvalue, которое обозначает объект, который не объявлен register и не является битовым полем.

  • Результат унарного разыменования (*) или оператора разыменования массива ([]).

  • Указатель функций.

Результат является указателем на operand_type, если тип операнда — operand_type.

Если операнд является результатом унарного оператора *, ни один из операторов не вычисляется, как если бы они оба были пропущены. Результат не является lvalue, и к операторам по-прежнему применяются ограничения. Если операнд является результатом оператора [], оператор & и унарный оператор *, подразумеваемый оператором [], не вычисляются. Результат будет таким же, как при удалении оператора & и смене оператора [] на +. В противном случае будет получен указатель на объект или функцию, назначаемую операндом.

Примеры

Далее в примерах используются следующие типичные объявления.

int *pa, x;
int a[20];

Эта инструкция использует оператор взятия адреса ( & ) для получения адреса шестого элемента массива a. Результат сохраняется в переменной указателя pa:

pa = &a[5];

Оператор косвенного обращения (*) в этом примере обращается к значению int, которое находится по адресу, сохраненному в переменной pa. Значение присваивается целочисленной переменной x:

x = *pa;

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

assert( x == *&x );

Этот пример показывает эквивалентные способы объявления указателя на функцию.

int roundup( void );     /* Function declaration */

int  *proundup  = roundup;
int  *pround  = &roundup;
assert( pround == proundup );

После объявления функции roundup объявляются и инициализируются два указателя на roundup. При инициализации первого из них, proundup, указывается только имя функции, а для второго, pround, используется оператор взятия адреса. Обе инициализации эквивалентны.

См. также

Оператор косвенного обращения: *
Оператор address-of: &