Указатели на указатели
В языке Си можно описать переменную типа «указатель на указатель». Это ячейка оперативной памяти, в которой будет храниться адрес указателя на какую либо переменную. Признак такого типа данных – повторение символа «*» перед идентификатором переменной. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:
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]
Отметим, что идентификатор двухмерного массива – это указатель на массив указателей (переменная типа указатель на указатель: int **m;), поэтому выражение а[i][j] эквивалентно выражению *(*(m+i)+j).
Например, двуxмерный массив m[3][4]; компилятор рассматривает как массив четырех указателей, каждый из которых указывает на начало массива со значениями размером по три элемента каждый.
Указатели | 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] |
(А) (В)
Рис. 4
Очевидна и схема размещения такого массива в памяти - последовательное (друг за другом) размещение "строк" - одномерных массивов со значениями. Аналогичным образом можно установить соответствие между указателями и массивами с произвольным числом измерений:
float name[][][][]; « float ****name;
Пример программы конструирования массива массивов:
#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 в следующем виде:
int z[3][4]={ 1, 2, 3, 4,
11,12,13,14, // Декларация и инициализация
21,22,23,24}; // массива массивов целых чисел
Замена скобочного выражения z[3][4] на z[12] здесь не допускается, так как массив указателей в данном случае создан не будет.
Дата добавления: 2015-09-11; просмотров: 548;