Иногда указатель может ссылаться на указатель, который ссылается на число. Это называется многоуровневой адресацией. Иногда применение таких указателей существенно усложняет программу, делает ее плохо читаемой и подверженной ошибкам. Рис. 5.3 иллюстрирует концепцию многоуровневой адресации. На рисунке видно, что значением «нормального» указателя является адрес объекта, содержащего нужное значение. В случае двухуровневой адресации первый указатель содержит адрес второго указателя, который содержит адрес объекта с нужным значением.
Многоуровневая адресация может иметь сколько угодно уровней, однако уровни глубже второго, т.е. указатели более глубокие, чем «указатели на указатели» применяются крайне редко. Дело в том, что при использовании таких указателей часто встречаются концептуальные ошибки из-за того, что смысл таких указателей представить трудно.
На заметку | Не следует путать многоуровневую адресацию с многоуровневыми структурами данных, использующими указатели, такими, например, как связные списки. Это фундаментально различные концепции. |
Переменная, являющаяся указателем на указатель, должна быть соответствующим образом объявлена. Это делается с помощью двух звездочек перед именем переменной. Например, в следующем операторе newbalance объявлена как указатель на указатель на переменную типа float:
float **newbalance;
Следует хорошо понимать, что newbalance — это не указатель на число типа float, а указатель на указатель на число типа float.
Указатель Переменная
+--------+ +--------+
| Адрес |------->|Значение|
+--------+ +--------+
Одноуровневая адресация
Указатель Указатель Переменная
+--------+ +--------+ +--------+
| Адрес |----->| Адрес |----->|Значение|
+--------+ +--------+ +--------+
Многоуровневая адресация
Рис. 5.3. Одноуровневая и многоуровневая адресация
При двухуровневой адресации для доступа к значению объекта нужно поставить перед идентификатором две звездочки:
#include <stdio.h>
int main(void)
{
int x, *p, **q;
x = 10;
p = &x;
q = &p;
printf("%d", **q); /* печать значения x */
return 0;
}
Здесь p объявлена как указатель на целое, a q — как указатель на указатель на целое. Функция printf() выводит на экран число 10.