Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Указатели и массивы
В языке "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, то тот факт, что ее аргумент в дейс- твительности ссылается к части большего массива,не имеет для нее никаких последствий.
Date: 2015-09-17; view: 360; Нарушение авторских прав |