Двухмерный массив и вспомогательный массив указателей

Приведем пример работы с двумерным массивом (матрицей) с использованием вспомогательного массива указателей.

# include <stdio.h>

# include <stdlib.h>

# include <time.h>

# define N 3

# define M 2

void main()

{

float matr[N][M];

float *pmatr[N];

srand(time(NULL));

printf("Доступ с помощью индексации имени массива:\n");

for (int i = 0; i<N; i++)

{

for (int j = 0; j<M; j++)

{

matr[i][j] = float (rand())/RAND_MAX*10;

printf("%3.1f\t", matr[i][j]);

}

printf("\n");

}

printf("Доступ с использованием вспомогательного массива:\n");

for (i = 0; i<N; i++)

pmatr[i] = &matr[i][0];

for (i = 0; i<N; i++)

{

for (int j = 0; j<M; j++)

printf("%3.1f\t", *(*(pmatr+i)+j));

printf("\n");

}

}

Доступ с помощью индексации имени массива называется прямым, а с помощью указателей вспомогательного массива – косвенным. Также отметим, что введенный массив pmatr также можно индексировать, т.е. запись *(*(pmatr+i)+j)) эквивалентна записи pmatr[i][j].

Так как указатель это переменная, в которой хранится адрес другой переменной, то С++ разрешает ввести «указатель на указатель» - т.е. переменную в которой будет храниться адрес ячейки памяти, в которой записан адрес другой ячейки. Синтаксис объявления «указателя на указатель» следующий:

тип **имя_указателя;

Следующий пример демонстрирует, как получить доступ к переменной, используя двойное разъименовывание указателя.

# include <stdio.h>

void main()

{

int A = 5; //переменная А

int *pA; //указатель на переменную А

int **ppA; //указатель на указатель pA

pA = &A; //получаем адрес переменной А

ppA = &pA; //получаем адрес указателя pA

printf("A = %d\n", **ppA);// получаем значение переменной А

}

Аналогично можно ввести «указатель на указатель на указатель» и т.д. Применяются они при работе с многомерными массивами.

# include <stdio.h>

void main()

{

int a = 10, b = 20, c = 30; //набор переменных

int * pM[3]; //массив указателей

pM[0] = &a; //записываем

pM[1] = &b; //в массив

pM[2] = &c; //адреса переменных a, b, c

int **ppM; //указатель на массив указателей

ppM = pM; //вспоминаем, что имя массива – адрес его

//первого элемента

//печатаем адреса переменных a, b, c хранящиеся в массиве pM

//и значения этих переменных, полученные с помощью указателя ppM

for (int i = 0; i<3; i++)

printf("&pM[%d] - %p\t%d\n", i, &pM[i], *(*(ppM+i)));

}

Результат работы программы:

&pM[0] - 0012FF68 10

&pM[1] - 0012FF6C 20

&pM[2] - 0012FF70 30

Заметим, что выражение *(*(ppM+i)) можно заменить эквивалентным, но более простым для понимания ppM[i][0].

Теперь рассмотрим, как можно разместить целочисленную матрицу размером N на M в динамической памяти. Алгоритм действия следующий.

1. Объявляем указатель на массив указателей int **pMatr;.

2. Выделяем память для хранения N указателей на первые элементов в каждой строке pMatr = new int * [N];.

3. В цикле выделяем память для хранения строк матрицы. Фактически эти строки можно рассматривать как одномерные массивы из M элементов.

for (i = 0; i<N; i++)

pMatr[i] = new int[M]; //в строке М элементов

Рисунок 6.1 – Схема имитации двухмерного динамического массива с помощью массива указателей и набора одномерных массивов.

Приведем программу, которая запрашивает размер матрицы и размещает ее в динамической памяти.

# include <stdio.h>

# include <stdlib.h>

# include <time.h>

void main()

{

int i, j, N, M;

printf("N = ");

scanf("%d", &N);

printf("M = ");

scanf("%d", &M);

int **pMatr;

pMatr = new int * [N];

for (i = 0; i<N; i++)

pMatr[i] = new int[M];

srand(time(NULL));

for (i = 0; i<N; i++)

{

for (j = 0; j<M; j++)

{

*(*(pMatr+i)+j) = rand()%11;

printf("%d\t", pMatr[i][j]);

}

printf("\n");

}

}

Еще раз обратим внимание на эквивалентность записей *(*(pMatr+i)+j) и pMatr[i][j]. Каждый может пользоваться формой, которая ему больше понятна.

Список рекомендуемой литературы.

1 Уэйт М., Прата С., Мартин Д. Язык Си. – М.: Мир, 1998.

2 Либерти Д. С++ за 21 день. – М.: Вильямс, 2000.

3 Подбельский В.В., Язык СИ++. – М.: Финансы и статистика, 2000.

4 Майкл Дж. Янг, Visual C++ 6, - Киев: «Ирина», 1999.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: