Массивы
Операции над указателями
Для типизированных указателей определены операции сложения с числом и вычитания из них числа, при этом результатом является указатель того же типа, смещенный в памяти на заданное количество данных (т.е. на размер данного, умноженного на заданное смещение).
Также для типизированных указателей определена операция разности указателей. Данная операция возвращает количество элементов (размер_области_памяти/размер_элемента) между указателями.
Пример 1 (будем считать, что sizeof(float)=4)
float *a=1000, *c;
short x;
c = a+10; // c = 1000+10*sizeof(float)=1040
c = c — 4; // c = 1040 — 4*sizeof(float) = 1024
x = c — a; // x = (1024-1000)/sizeof(float) = 6
Пример 2:
int x;
float y;
void *t = &x; //допустимо
*t = 5; // операция НЕДОПУСТИМА, т.к. неизвестен
//тип данного
*(int *)t = 5; //допустимо обращение при соответствующем
//приведении типов
t =& y;
*(double*)t = 2.5;
Массивы являются набором однотипных данных, последовательно размещённых в памяти.
Одномерный массив можно объявить так:
тип_данного имя_массива[размер];
Например: int x[5];
|
|
Обращение к элементам массива происходит через операцию []. Минимальный индекс всегда ноль. Максимальный индекс — на единицу меньше размера массива.
ВНИМАНИЕ Автоматический контроль границ отсутствует.
Возможно создать массив требуемого размера во время выполнения программы. Например, в библиотеке stdlib.h определены функции malloc для выделения памяти и free для её освобождения.
Пример
int *x;
x = (int*)malloc(10*sizeof(int)); // выделение памяти для 10 //элементов типа «int»
/* некоторый код по обработке массива */
free(x); // освобождение памяти
Более подробно данные функции будут рассмотрены ниже.
В «С++» для выделения памяти под массив элементов определены операции new[] и delete[].
Пример (аналогичный по функциональности предыдущему)
int *x;
x = new int[10];
…
delete []x;
Возможны по крайней мере три варианта реализации многомерных массивов.
1. Использование средств языка: возможность объявить массив массивов. В этом случае размер по каждому измерению указывается в отдельных квадратных скобках. Обращение к элементам происходит аналогично одномерному массиву.
Пример
int x[4][4][3];
x[0][0][0] = 5;
Массивы могут инициализироваться значениями в фигурных скобках, при этом допустимо не указывать последнюю (самую левую) размерность. Если заданная размерность меньше инициализирующих аргументов, часть элементов останется неопределенна. Обратная ситуация вызовет ошибку.
Примеры
int x[3][2]={{1,2},{3,4},{5,6}}; //заданы и размеры массива,
//и инициализирующие значения
long y[] = {1,2,3,4}; // размер массива определяется по
//фактическому по количеству значений (4)
char t[][4] = {{1,2,3,4},{5,6}}; // последняя размерность определяется //по числу значений (2) и элементы t[1][2] и t[1][3] не определены
|
|
При таком указании данные располагаются в памяти последовательно, порядок расположения соответствует порядку указания при инициализации.
2. Использование многомерных указателей. В этом случае каждую размерность указателя требуется явно инициализировать. Таким способом можно получить, например, двумерный массив с различной длиной строк.
Пример
int **x;
x = new int*[3];
for(int i=0;i<3;i++) x[i] = new int[i];
x[0][0] = 0; x[1][0] = 1; x[1][1] = 2; x[2][0] = 3; x[2][1]=4; x[2][2] = 5;
Получаем массив вида
В этом случае в памяти отдельно хранится массив указателей на строки и отдельно сами строки.
3. Хранение многомерного массива в одномерном.
Например, переход от двух индексов (i,j) к одному (k) можно осуществить по формуле k=i*m+j, где m — размерность по j (количество столбцов). Обратный переход: i=k/m, j=k%m.