Указатели и адреса
Так как указатель содержит адрес объекта, это дает воз- можность "косвенного" доступа к этому объекту через указа- тель. Предположим, что х - переменная, например, типа INT, а рх - указатель, созданный неким еще не указанным способом. Унарная операция & выдает адрес объекта, так что оператор
рх = &х;
присваивает адрес х переменной рх; говорят, что рх "ука- зывает" на х. Операция & применима только к переменным и элементам массива, конструкции вида &(х-1) и &3 являются не- законными. Нельзя также получить адрес регистровой перемен- ной. Унарная операция * рассматривает свой операнд как адрес конечной цели и обращается по этому адресу, чтобы извлечь содержимое. Следовательно, если Y тоже имеет тип INT, то
Y = *рх;
присваивает Y содержимое того, на что указывает рх. Так пос- ледовательность
рх = &х; Y = *рх;
присваивает Y то же самое значение, что и оператор
Y = X;
Переменные, участвующие во всем этом необходимо описать:
INT X, Y; INT *PX;
с описанием для X и Y мы уже неодонократно встречались. Описание указателя
INT *PX;
является новым и должно рассматриваться как мнемоническое; оно говорит, что комбинация *PX имеет тип INT. Это означает, что если PX появляется в контексте *PX, то это эквивалентно переменной типа INT. Фактически синтаксис описания перемен- ной имитирует синтаксис выражений, в которых эта переменная может появляться. Это замечание полезно во всех случаях, связанных со сложными описаниями. Например,
DOUBLE ATOF(), *DP;
говорит, что ATOF() и *DP имеют в выражениях значения типа DOUBLE.
Вы должны также заметить, что из этого описания следу- ет, что указатель может указывать только на определенный вид объектов. Указатели могут входить в выражения. Например, если PX указывает на целое X, то *PX может появляться в любом кон- тексте, где может встретиться X. Так оператор
Y = *PX + 1
присваивает Y значение, на 1 большее значения X;
PRINTF("%D\N", *PX)
печатает текущее значение X;
D = SQRT((DOUBLE) *PX)
получает в D квадратный корень из X, причем до передачи фун- кции SQRT значение X преобразуется к типу DOUBLE. (Смотри главу 2). В выражениях вида
Y = *PX + 1
унарные операции * и & связаны со своим операндом более крепко, чем арифметические операции, так что такое выражение берет то значение, на которое указывает PX, прибавляет 1 и присваивает результат переменной Y. Мы вскоре вернемся к то- му, что может означать выражение
Y = *(PX + 1)
Ссылки на указатели могут появляться и в левой части присваиваний. Если PX указывает на X, то
*PX = 0
полагает X равным нулю, а
*PX += 1
увеличивает его на единицу, как и выражение
(*PX)++
Круглые скобки в последнем примере необходимы; если их опус- тить, то поскольку унарные операции, подобные * и ++, выпол- няются справа налево, это выражение увеличит PX, а не ту пе- ременную, на которую он указывает. И наконец, так как указатели являются переменными, то с ними можно обращаться, как и с остальными переменными. Если PY - другой указатель на переменную типа INT, то
PY = PX
копирует содержимое PX в PY, в результате чего PY указывает на то же, что и PX.