Например, * (mas + 1) = 3 или { i = 0; *(mas +i+2)=7; }.
При реализации на компьютере первый способ осуществляется через второй, т.е. индексное выражение mas[i] преобразуется к адресному *(mas + i), а поскольку от перемены мест слагаемых сумма не меняется, то записи mas[i] и i[mas] будут эквивалентными и обозначают элемент массива с номером i.
3.4. «НАСТРОЙКА» УКАЗАТЕЛЯ НА МАССИВ
Указатель, используемый и в индексном выражении, и в операции раскрытия ссылки, не обязательно должен быть константой-указателем, он может быть и переменной-указателем. В частности, если объявить переменную ptr с инициализацией int *ptr = mas; – доступ к 1-му элементу массива mas можно получить с помощью указателя ptr в форме ptr[1] или в форме * (ptr + 1).
Такая «настройка» переменной-указателя на массив, предусматривающая возможность изменения самого указателя, сокращает время доступа, повышая тем самым скорость выполнения программы.
В примере 3.1 оператор цикла уменьшит на 1 значения всех элементов исходного массива.
Пример 3.1.
int j, mas[] = {10, 43, 24, 15, 7}; int *ptr = mas;
for (j=0,j<5;j++) --*ptr++;
Подобные действия с именем массива (т.е. mas++ ) – не допустимы, т.к. mas – имя константы, которая не может быть изменена.
Явные преимущества возникают при настройке переменных-указателей на символьные массивы. Классическим примером является прием инвертирования строки, представленный в примере 3.2. Инвертирование строки можно осуществить и без указателей с использованием индексации, но такой способ и более трудоемок, и дольше выполняется на компьютере.
Пример 3.2.
# include <stdio.h>
void main()
{ char*p, * q, str[] = "advantage", sim;
p = st; q = &str[8];
while (p < q) {sim = *p; *p++ = *q; *q-- = sim;}
p=p-4;
printf("\n new stroka = %s ",p); }
Именно с использованием настройки указателей на строки работают библиотечные функции обработки строк, в частности, функция копирования строк и функция вычисления длины строки (общего количества символов в строке без нулевого символа). В примере 3.3 в главной функции происходит копирование строки с константным адресом str в участок памяти с начальным адресом st. Одновременно вычисляется и длина r исходной (и новой) строки.
Пример 3.3.
# include <stdio.h>
void main()
{ char st[10], str[] = "advantage";
char *p = str, * q=st; int r=0;
for (;*p;*q++ = *p++, r++);
*q='\0';
printf("\n new stroka = %s ",st); printf("\n dlina stroki = %d ",r);
}
Циклfor используется без тела, копирование происходит в заголовке цикла, в операторе изменения значений параметров цикла. Оператор присваивания *q++ = *p++; выполняется так же, как последовательность операторов: *q = *p; q = q + 1; p = p + 1;
Цикл прекращается, когда выражение *p обращается в 0, это происходит после смещения указателя p к нулевому символу, завершающему исходную строку. Поэтому копирование нулевого символа не происходит, что делает необходимым наличие оператора *q='\0';. (иначе на экране после слова «advantage» появятся произвольные символы, так называемый «мусор»).
3.5. ФУНКЦИИ ДЛЯ РАБОТЫ С ДИНАМИЧЕСКОЙ ПАМЯТЬЮ
С использованием переменных-указателей программа может динамически (т.е. по мере возникновения необходимости при выполнении) запрашивать дополнительные области оперативной памяти и использовать их по своему усмотрению, в том числе и освобождать уже не нужные участки памяти.
Программа получает доступ к механизму распределения динамической памяти, если в ее исходном тексте присутствует директива препроцессору #include <stdlib.h>, в соответствии с которой в программу включается заголовочный файл stdlib.h, содержащий прототипы всех библиотечных функций, работающих с динамической памятью. Рассмотрим 5 функций.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.