Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | ||
|
Связь указателей и массивов с одним измерением справедливо и для массивов с большим числом измерений. Например, рассмотрим двумерный массив
float m[5][10];
Если рассматривать его как массив пяти массивов размерностью по десять элементов каждый, то очевидна схема его размещения в памяти - последовательное размещение «строк» элементов. Обращению к элементам m[i][j] соответствует эквивалентное выражение *(*(m+i)+j), а объявление этого массива указателем будет:
float **m;
Таким образом, имя двумерного массива - имя указателя на указатель.
Например, двухмерный массив m(3х4) компилятор рассматривает как массив трех указателей, каждый из которых указывает на начало массива со значениями размером по четыре элемента каждый (рис. 1).
m | значения | ||||||
Ука- | m[0] | → | m[0][0] | m[0][1] | m[0][2] | m[0][3] | *(*(m+i)+j) |
за- | m[1] | m[1][0] | m[1][1] | m[1][2] | m[1][3] | ||
тели | m[2] | m[2][0] | m[2][1] | m[2][2] | m[2][3] |
рис. 1
Cхема размещения такого массива в памяти - последовательное (друг за другом) размещение строк - одномерных массивов со значениями.
Аналогичным образом можно установить соответствие между указателями и массивами с произвольным числом измерений. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:
int a=5;
int *p1=&a;
int **pp1=&p1;
int ***ppp1=&pp1;
Теперь присвоим целочисленной переменной а новое значение, например 10. Одинаковое присваивание произведут следующие операции:
a=10;
*p1=10;
**pp1=10;
***ppp1=10;
Для доступа к области памяти, отведенной под переменную а можно использовать и индексы. Справедливы следующие аналоги:
*p1 равносильно p1[0]
**pp1 равносильно pp1[0][0]
***ppp1 равносильно ppp1[0][0][0]
Таким образом, указатели на указатели – это имена многомерных массивов.
Очевидна эквивалентность выражений:
&name[0][0] <-> &(**name) <-> name // адрес нулевого элемента матрицы
**name <-> name[0][0] // значение нулевого элемента матрицы
Пример программы:
#include <stdio.h>
int x0[4]={ 1, 2, 3, 4};
int x1[4]={11,12,13, 14}; // Декларация и инициализация
int x2[4]={21,22,23, 24}; // массивов целых чисел
int *y[3]={x0, x1, x2}; // Создание массива указателей
void main(void)
{
int i,j;
for (i=0; i<3; i++)
{
printf("\n %2d)",i);
for (j=0; j<4; j++) printf(" %2d",y[i][j]);
}
}
Результаты работы программы:
0) 1 2 3 4
1) 11 12 13 14
2) 21 22 23 24
Такие же результаты получим и при следующем объявлении массива:
int y[3][4]={{1,2,3,4},{11,12,13,14},{21,22,23,24}}; // Декларация и инициализация матрицы целых чисел
В последнем случае массив указателей на массивы создается компилятором. Здесь собственно данные массива располагаются в памяти последовательно по строкам, что является основанием для объявления y в виде
z[3][4]={ 1, 2, 3, 4, 11,12,13,14, 21,22,23,24}; // Декларация и инициализация матрицы целых чисел
скобочного выражения z[3][4] на z[12] здесь не допускается, так массив указателей в данном случае создан не будет.
Дата публикования: 2014-11-28; Прочитано: 184 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!