Многоуровневая адресация

Содержание

Иногда указатель может ссылаться на указатель, который ссылается на число. Это называется многоуровневой адресацией. Иногда применение таких указателей существенно усложняет программу, делает ее плохо читаемой и подверженной ошибкам. Рис. 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.