[Оглавление] | [<< страница] | [>>страница] |
1.7. Особенности использования массивов в языке
Си
В соответствии с синтаксисом Си в языке допускаются только одномерные массивы. Однако элементами массива также могут быть массивы, следовательно, массив массивов можно рассматривать как двухмерный массив. Аналогично можно использовать и многомерные массивы.
Объявление N-мерного массива имеет вид:
тип <имя массива> [размер1][размер2]...[размер],
где тип — базовый тип элементов массива;
размер i — число значений i-го индекса массива. Размер задается константой или
константным выражением, массивы переменного размера не допускаются. Индекс всегда
начинается с нуля. Таким образом, первым элементом массива является элемент с
нулевыми индексами. В языке Си в отличие от языков ПЛ/1 и Паскаль нет средств
поддержки контроля выхода индексов за установленные пределы.
Для массива транслятор Си всегда выделяет участок непрерывной оперативной памяти, размеры которого определяются числом элементов массива и длиной элемента (т.е. базовым типом). Таким образом, размер выделяемой под массив памяти фиксирован. Так как программы разрабатываются для решения определенного класса задач, то обычно размер массива выбирается по максимуму, в результате при решении конкретной задачи часть памяти может расходоваться впустую. Если же задавать предельно маленький размер массива, то может потребоваться часто редактировать исходную программу, изменяя размеры массивов, и заново транслировать программу.
Выходом из этого положения могут служить динамическое выделение необходимой памяти и последовательное размещение там элементов массива, т.е. хранение массива в виде вектора. В случае одномерного массива доступ к его элементам осуществляется обычным использованием индекса, т.е. индексы массива и вектора совпадают. Доступ к элементам двухмерного массива потребует вычисления индекса вектора по индексам двухмерного массива.
Между массивами и указателями в Си имеется тесная связь, которая существенно используется при разработке программ. При динамическом выделении памяти для массива не обойтись без указателей. Применение указателей во многих случаях позволяет обойти трудности, связанные с фиксированными размерами статических массивов.
При использовании указателей массивов необходимо обратить внимание на
следующие моменты:
— Имя массива является указателемконстантой, поэтому его значение изменить
невозможно. Так, если массив определен как int A[5], то А[1] или *(А+1) указывает
на второй элемент массива, но выражение А++ недопустимо.
— Ответственность за проверку выхода за границы массива полностью лежит на
программисте.
В Си все параметры функции, за исключением параметров типа «указатель» и «массив», передаются по значению. Если в качестве параметра функции передается массив, то на самом деле внутрь функции попадает только начальный адрес массива.
Рассмотрим это подробнее. Поскольку при передаче массива в
функцию попадает только его начальный адрес, а все элементы как одномерного, так и
многомерного массива размещаются в последовательных ячейках памяти (в векторной
памяти), то в функции вид обращения к элементам массива полностью определяется
прототипом функции. Так, если прототип функции имеет вид:
fl(int*a, int*b,...) или fl(int a[], int b[],...),
то предполагается, что функция обрабатывает массивы а и b как одномерные. Тогда
обращение к элементу массива осуществляется по одномуединственному индексу этого
элемента. Если исходный массив (фактический параметр) является одномерным, то
индексы элементов массива в функции и исходного массива совпадают, т.е. элементу
A[i] исходного массива соответствует элемент а[i] в функции (или *(a+i), что
равносильно). Если же исходный массив является многомерным, то значения индексов
элементов массива в функции придется вычислять. Так, если исходный массив описан
как int A[M][N], ТО его элементу А[i][j] в функции будет соответствовать элемент
a[i*n+j) (или *(a+i*n+j)). Рассмотренный подход позволяет использовать функцию для
обработки как динамических, так и статических массивов.
Если в функции предполагается обработка многомерного массива с использованием всех его индексов, то размеры всех их, за исключением первого, должны быть указаны в прототипе, например f2(float a[][n][p],...). При этом обращение к элементу массива в функции будет осуществляться по его индексам: a[i][j][k]. Нельзя упускать из виду, что размеры индексов массива задаются константными выражениями.
[Оглавление] | [<<страница] | [>>страница] | [В начало ] |