int a[] = { 0,1,2,3,4 }; | Переменная a инициируется как массив из пяти целых. |
int *p[] = { a,a+1,a+2,a+3,a+4 }; | Если в выражении встречается *p[], оно вычисляется как целое, т.е. p[] должно указывать не целое, и p - массив ссылок на целое. Пять элементов массива p вначале указывают на пять элементов массива a. |
int **pp=p; | Выражение **pp вычисляется как целое, значит, *pp должно быть ссылкой на целое, а pp - указывать на ссылку на целое. Вначале pp указывает на p[0]. |
Рис.2.1 показывает взаимосвязь между pp, p и a.
Рис.2.1. |
PRINT2(d, a, *a); | Как уже указывалось ранее, имя массива - синоним адреса первого элемента массива. Значит, значение a - адрес начала массива a и эквивалентно a[0]. |
PRINT3(d, p, *p, **p); | Значение p считается адресом первого элемента массива p, *p дает значение первого элемента массива, т.е. p[0], а *pp выдает целое, находящееся по адресу, хранящемуся в p[0], т.е. значение a[0]. |
PRINT3(d, pp, *pp, **pp); | Параметр pp относится к содержимому pp, т.е. адресу p. *pp дает целое, на которое ссылается p[0], или a[0]. |
pp++ | Переменная pp - это ссылка на ссылку на целое (базовый тип pp - ссылка на целое), так что pp++ настраивает pp на следующую ссылку в память. Действие операции ++ показано на рис.2.3-1 жирной стрелкой. |
pp-p | Ссылка pp указывает на второй элемент массива p, т.е. на p[1]. Таким образом, значение pp есть p+1. pp-p=(p+1)-p, т.е. 1. |
*pp-a | Ссылка pp указывает на p[1], и *pp указывает на второй элемент массива a. Таким образом, значение *pp есть a+1, а *pp-a=(a+1)-a. |
**pp | Выражение *pp указывает на a[1], так что *pp дает содержимое a[1]. |
*pp++ | *(pp++) Унарные операции выполняются справа налево, поэтому вначале выполняется операция ++, а затем - косвенное обращение. Жирная стрелка на рис.2.3-2 показывает действие операции ++. |
*++pp | *(++pp) (рис.2.3-3) |
++*pp | ++(*pp) (рис.2.3-4) |
Рис.2.3-1 |
Рис.2.3-2 |
Рис.2.3-3 |
Рис.2.3-4 |
Рис.2.4-1 pp=p |
Рис.2.4-2 *(*(pp++)) |
Рис.2.4-3 *(++(*pp)) |
Рис.2.4-4 ++(*(*pp)) |