Простейшие типы данных
[Оглавление] [<< страница] [>>страница]


   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]. Нельзя упускать из виду, что размеры индексов массива задаются константными выражениями.

[Оглавление] [<<страница] [>>страница] [В начало ]