Язык С




Указатели и массивы - часть 2


PA = A

Еще более удивительным, по крайней мере на первый взг- ляд, кажется тот факт, что ссылку на A[I] можно записать в виде *(A+I). При анализировании выражения A[I] в языке "C" оно немедленно преобразуется к виду *(A+I); эти две формы совершенно эквивалентны. Если применить операцию & к обеим частям такого соотношения эквивалентности, то мы получим, что &A[I] и A+I тоже идентичны: A+I - адрес I-го элемента от начала A. С другой стороны, если PA является указателем, то в выражениях его можно использовать с индексом: PA[I] иден- тично *(PA+I). Короче, любое выражение, включающее массивы и индексы, может быть записано через указатели и смещения и наоборот, причем даже в одном и том же утверждении.

Имеется одно различие между именем массива и указателем, которое необходимо иметь в виду. указатель является перемен- ной, так что операции PA=A и PA++ имеют смысл. Но имя масси- ва является константой, а не переменной: конструкции типа A=PA или A++,или P=&A будут незаконными. Когда имя массива передается функции, то на самом деле ей передается местоположение начала этого массива. Внутри вызванной функции такой аргумент является точно такой же пе- ременной, как и любая другая, так что имя массива в качестве аргумента действительно является указателем, т.е. Перемен- ной, содержащей адрес. мы можем использовать это обстоятель- ство для написания нового варианта функции STRLEN, вычисляю- щей длину строки.

STRLEN(S) /* RETURN LENGTH OF STRING S */ CHAR *S; { INT N;

FOR (N = 0; *S != '\0'; S++) N++; RETURN(N); }

Операция увеличения S совершенно законна, поскольку эта переменная является указателем; S++ никак не влияет на сим- вольную строку в обратившейся к STRLEN функции, а только увеличивает локальную для функции STRLEN копию адреса. Опи- сания формальных параметров в определении функции в виде

CHAR S[]; CHAR *S;

совершенно эквивалентны; какой вид описания следует предпо- честь, определяется в значительной степени тем, какие выра- жения будут использованы при написании функции. Если функции передается имя массива, то в зависимости от того, что удоб- нее, можно полагать, что функция оперирует либо с массивом, либо с указателем, и действовать далее соответвующим обра- зом. Можно даже использовать оба вида операций, если это ка- жется уместным и ясным. Можно передать функции часть массива, если задать в ка- честве аргумента указатель начала подмассива. Например, если A - массив, то как

F(&A[2])

как и

F(A+2)

передают функции F адрес элемента A[2], потому что и &A[2], и A+2 являются указательными выражениями, ссылающимися на третий элемент A. внутри функции F описания аргументов могут присутствовать в виде:

F(ARR) INT ARR[]; { ... }

или

F(ARR) INT *ARR; { ... }

Что касается функции F, то тот факт, что ее аргумент в дейс- твительности ссылается к части большего массива,не имеет для нее никаких последствий.




    Содержание  Назад  Вперед