В языке "C" существует сильная взаимосвязь между указа-телями и массивами , настолько сильная, что указатели и мас-сивы действительно следует рассматривать одновременно. Любуюоперацию, которую можно выполнить с помощью индексов масси-ва, можно сделать и с помощью указателей. вариант с указате-лями обычно оказывается более быстрым, но и несколько болеетрудным для непосредственного понимания, по крайней мере дляначинающего. описание INT A[10] определяет массив размера 10, т.е. Набор из 10 последова-тельных объектов, называемых A[0], A[1], ..., A[9]. ЗаписьA[I] соответствует элементу массива через I позиций от нача-ла. Если PA - указатель целого, описанный как INT *PA то присваивание PA = &A[0] приводит к тому, что PA указывает на нулевой элемент массиваA; это означает, что PA содержит адрес элемента A[0]. Теперьприсваивание X = *PA будет копировать содержимое A[0] в X. Если PA указывает на некоторый определенный элемент мас-сива A, то по определению PA+1 указывает на следующий эле-мент, и вообще PA-I указывает на элемент, стоящий на I пози-ций до элемента, указываемого PA, а PA+I на элемент, стоящийна I позиций после. Таким образом, если PA указывает наA[0], то *(PA+1) ссылается на содержимое A[1], PA+I - адрес A[I], а *(PA+I) -содержимое A[I]. Эти замечания справедливы независимо от типа переменныхв массиве A. Суть определения "добавления 1 к указателю", атакже его распространения на всю арифметику указателей, сос-тоит в том, что приращение масштабируется размером памяти,занимаемой объектом, на который указывает указатель. Такимобразом, I в PA+I перед прибавлением умножается на размеробъектов, на которые указывает PA. Очевидно существует очень тесное соответствие между ин-дексацией и арифметикой указателей. в действительности ком-пилятор преобразует ссылку на массив в указатель на началомассива. В результате этого имя массива является указатель-ным выражением. Отсюда вытекает несколько весьма полезныхследствий. Так как имя массива является синонимом местополо-жения его нулевого элемента, то присваивание PA=&A[0] можнозаписать как 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, то тот факт, что ее аргумент в дейс-твительности ссылается к части большего массива,не имеет длянее никаких последствий.