Многомерные массивы хранятся в памяти так, что самый правый индекс массива изменяется первым. Тогда для двумерного массива int A[2][3]; порядок хранения элементов такой: A[0][0], A[0][1], A[0][2], A[1][0], A[1][1], A[1][2]. Если мы введем указатель int *pA = &AA[0][0], то *pA – элемент с индексами [0][0], *(pA+3) – элемент с индексами [1][0]. Приведенная ниже программа наглядно демонстрирует это.
#include <stdio.h>
void main()
{
int *pA;
int AA[3][2];
pA = &AA[0][0];
printf("Dostup po indexu:\n");
for (int i = 0; i<3; i++)
{
for (int j = 0; j<2; j++)
{
AA[i][j] = i + j;
printf("%p-%d\t", &AA[i][j], AA[i][j]);
}
printf("\n");
}
printf("\nDostup s ispolzovaniem ukazatelya:\n");
for (i = 0; i<2*3; i++)
printf("%p-%d\n", pA+i, *(pA+i));
printf("\n");
}
Результат работы программы:
Dostup po indexu:
0012FF64-0 0012FF68-1
0012FF6C-1 0012FF70-2
0012FF74-2 0012FF78-3
Dostup s ispolzovaniem ukazatelya:
0012FF64-0
0012FF68-1
0012FF6C-1
0012FF70-2
0012FF74-2
0012FF78-3
Как видно из этого примера адреса элементов, полученные с помощью указания индексов, полностью совпадают с адресами элементов, полученных с помощью указателя. Обратите внимание, что адреса элементов отличаются друг от друга на 4 байта, ровно столько занимает переменная типа int.
|
|
Приведенный выше пример вполне работоспособен, однако, он обладает рядом недостатков. Например, используя указатель pA, сложно распределить двумерный массив в динамической памяти. Для таких целей (да и просто для работы с многомерными массивами) рекомендуется использовать массивы указателей. Рассмотрим этот момент подробнее.
Допустим в программе нужно хранить список из 3 фамилий. Каждая фамилия может быть произвольной длины, но не больше, допустим, 20 символов. Данное требование можно выполнить, объявив двумерный массив символов char spisok[3][20]; т.е. 3 фамилии, по 20 символов для каждой. Тогда всего будет выделено 1байт * 20 символов * 3 фамилии = 60 байт.
Эту же задачу можно решить другим способом, а именно, объявив массив указателей char *sp [3] = {"Иванов", "Сидоров", "Козликов"}; Всего в этом массиве будет 3 элемента и каждый из них является указателем типа char *, для этого будет выделено 3*sizeof(char *) = 12 байт. Кроме того, компилятор размещает в памяти 3 строковые константы "Иванов" (7 байт), "Сидоров" (8 байт), "Козликов" (9 байт), а их адреса становятся значениями элементов sp[0], sp[1], sp[2]. Т.е. всего выделяется 12+7+8+9 = 36 байт. Выигрыш по сравнению с первым случаем очевиден.