5.2.1. Взаимосвязь
указателей и массивов. Массивы указателей.
В языке Си существует сильная
взаимосвязь между указателями и массивами. Любое
действие, которое достигается индексированием
массива, может быть выполнено также с помощью
указателей, причём последний вариант будет
быстрее.
Объявление int a[5]; определяет массив из 5-ти элементов: a[0],
a[1],…,a[4]. Если объект *y объявлен как int *y;, то оператор y=&a[0]; присваивает переменной y адрес элемента a[0] (см. рисунок 1).

Если переменная y указывает на очередной элемент
массива a, то y+1 указывает на следующий элемент,
причём выполняется соответствующее масштабирование
для приращения адреса с учётом длины объекта (для
int - 2 байта, long – 4 байта и т.п.). Поскольку имя
массива есть адрес его нулевого элемента,
инструкция y=&a[0]; может
быть записана по-другому: y=a;. Тогда элемент a[i] можно представить как *(a+i). С другой стороны,
если y – указатель, то записи: y[i]
и *(y+i) – эквивалентны.
Таким образом, любой массив и индексное выражение
можно представить посредством указателей. В тоже время между именем массива и
соответствующим указателем есть одно различие.
Указатель – это переменная
и y=a; или y++;
- допустимые операции. Имя же массива – константа. Поэтому
конструкции вида a=y; a++; z=&a;
использовать нельзя, т.к. значение константы постоянно
и не может быть изменено.
Указатели, адресующие
элементы одного массива,
можно сравнивать. Но нельзя
сравнивать, либо применять в
арифметических операциях. Указатели на разные
массивы.
Кроме того, в Си допускаются массивы
указателей, которые объявляются, например, так:
char *m[5];. Здесь объявляется
массив, содержащий адреса 5-ти элементов типа char.
Рассмотрим программу, которая
осуществляет упорядочение строк массива s в порядке убывания кодов первой
буквы.
Пусть в массиве s пять строк. Введём массив m указателей на строки массива s. Тогда для упорядочения s достаточно изменить надлежащим
образом значения элементов m. Окончательно
для элементов m[0], m[1],…,m[4]
необходимо последовательно вывести на экран
строки, на которые они указывают.

Вспомогательный массив ind необходим для повторного обращения
к строке. Первоначально все
его элементы имеют нулевое значение. Если ind[i]=1, то i-я строка уже
рассматривалась, и на очередной итерации её
нужно пропустить. На первом шаге значением q является индекс строки с наибольшим
кодом первой буквы. На следующем шаге строка с
этим номером исключается, и теперь значением q является индекс со следующим по
величине кодом первой буквы и т.д. |