Массив — это сложный (составной, структурированный) тип данных, который характеризуется следующим:
· элементы массива имеют одинаковый тип в отличие от структур, поэтому каждый элемент массива занимает одинаковый объём памяти;
· массив располагается в оперативной памяти, а не на внешнем устройстве, как файлы (2-й семестр);
· элементы массива занимают подряд идущие ячейки, в отличие, например, от списков (2-й семестр).
Доступ к элементам массива в языке С++ осуществляется двумя способами.
Первый, с помощью порядкового номера элемента массива, который называется индексом, характерен для многих языков программирования и рассматривается в первом семестре. Он более простой и привычный для тех, кто изучал язык Pascal. В качестве индекса можно использовать выражение целого или совместимого с ним типа, в том числе константу или переменную. В качестве индекса нельзя использовать выражение вещественного типа.
Кроме того, в языке С++ есть возможность обрабатывать массивы, используя указатели (адреса), так как в С++ существует связь между массивами и указателями. Несмотря на то, что в первом способе в программе отсутствует специальный тип для работы с адресами, указатели всё равно используются.
Массивы могут иметь одну или несколько размерностей. В этом параграфе рассматривается одномерный массив, который иногда называют вектором, подразумевая вектор в n-мерном пространстве. Работа с двумерными массивами (матрицами) рассматривается в гл. 5. Три и более размерностей на практике используются редко, так как такие массивы занимают большой объём оперативной памяти.
Везде в дальнейшем под словом “массив” будем понимать одномерный массив.
С точки зрения времени (этапа), когда распределяется память под массив, существуют два их вида. Память для динамического массива выделяется во время выполнения программы, и если массив не нужен, память для него можно освободить. Такие массивы рассматриваются во втором семестре.
Одномерный массив с фиксированной размерностью (назовём его статический) объявляется в общем виде следующим образом:
тип имя [N];
Здесь тип — тип элементов массива. Вначале будем рассматривать простые типы (int, float, char), но можно использовать и сложные, например, структуры. Имя записывается по правилам идентификаторов. Каждый элемент массива имеет одно и то же имя, меняется только индекс или номер элемента. N — размерность (или размер) массива в виде целочисленной константы или константного выражения. Эта величина определяет количество ячеек оперативной памяти, зарезервированной для массива. Например:
float A[10]; или const n=10; float A[n];
Преимущество второго способа c предварительным объявлением размерности в виде константы заключается в следующем. Если надо будет изменить размерность массива, то это достаточно сделать в одном месте программы при определении константы.
В отличие от динамического массива, для статического на этапе компиляции резервируется память для размещения N чисел указанного типа (10 вещественных чисел). Для массива требуется память объёмом k*N байт (4*10), где k — необходимое количество байт для размещения одного элемента указанного типа (одного числа типа float). Эта память сохраняется на всё время выполнения программы, а точнее, функции или блока, где описан массив. Программно необходимый объём памяти определяется с помощью операции sizeofследующим образом:
M=sizeof (тип)*N; или M= sizeof (имя); или M= sizeof имя;
где M — переменная целого типа, определяющая размер массива в байтах. Тип обязательно записывается в скобках, а имя может быть без скобок. Следующая программа выведет дважды число 40.
float A[10]; int M1, M2;
M1=sizeof(float)*10; // но M1=sizeof float *10;— ошибка!
M2=sizeof(A); // или M2=sizeof A;
cout<<M1<<endl<<M2;
Во многих современных системах программирования, в том числе и в С++, нумерация элементов массива начинается с 0. Тогда A[n-1] — последний элемент массива. Это связано с использованием указателей при работе с массивами (см. 2-й семестр). Поэтому в нашем примере индекс изменяется от 0 до 9 включительно, то есть индекс последнего элемента массива на единицу меньше его размерности. Объявленные 10 элементов массива обозначаются следующим образом: A[0], A[1], A[2] ,…, A[9]. В С++ отсутствует проверка границ массивов. Можно выйти за его границу и записать значение в некоторую переменную или даже в код программы. О таком контроле должен позаботиться программист.
При использовании статических массивов возникают проблемы в случае, если размер массива заранее мы не знаем. В таком случае объявляем массив максимальной размерности, которая, как правило, известна. Реальную размерность вводим и используем далее, например, в циклах и для других целей:
const nmax=100; float X[nmax];
int n; cout<<”Input the size of array ”; cin>>n;
/* Дальше работаем с n (а не с nmax) элементами массива, например, вводим их.*/
for (int i=0; i<n; i++)
{ // Эту строку можно опустить вместе с фигурными скобками.
cout<<”X[“<<i<<”]=”;
cin>>X[i];
}
Такой способ проще, но неэффективен с точки зрения распределения памяти, так как “заказываем” больше памяти, чем реально используем. В таких случаях профессионально используются более эффективные динамические массивы (см. 2-й семестр).