Многоуровневые указатели
Рассмотрим определение переменной:
double **pp;
В соответствии принципом контекстного определения pp нужно интерпретировать как переменную, при косвенном обращении к которой получается указатель на переменную типа double , то есть как указатель на указатель или адрес указателя. Но поскольку любой указатель в Си может ссылаться как на отдельную переменную, так и на область памяти (массив), то в применении к двойному указателю получаются 4 варианта структур данных, а именно:
-указатель на одиночный указатель на переменную типа double ;
-указатель на одиночный указатель на массив переменных типа double ;
-указатель на массив, содержащий указатели на одиночные переменные типа double ;
-указатель на массив, содержащий указатели на массивы переменных типа double .
Третья интерпретация позволяет нам использовать двойной указатель для работы с известными нам массивами указателей следующим образом:
double **pp, *pd[20];
pp = pd; // или pp = &pd[0];
*(pp+i) // или pp[i]
**(pp+i) // или *pp[i]
Здесь повторяется та же самая система эквивалентности обычных массивов и указателей -типов double* и double[], но применительно не к массивам обычных переменных, а к массивам указателей. Короче говоря, типы double** и double *[] различаются так же, как указатель-переменная и указатель-константа.
Массив указателей типа double *[] является статической структурой данных, размерность которой определяется при трансляции. Двойной указатель типа double** может ссылаться и на динамический массив указателей, который создается во время работы программы под заданную размерность:
//------------------------------------------------------bk52-02.cpp
double **create(int sz)
{ double **pp,*q; // создать динамический массив
int i; // указателей размерностью sz+1
pp = new double *[sz+1];
for (i=0; i<sz; i++) // создать динамическую переменную
{
q = new double;
*q = i; // указатель занести в динамический
pp[i] = q; // массив
}
pp[sz] = NULL;
return(pp); // возвратить указатель
} // на динамический массив указателей