Мое личное мнение таково, что картинки со стрелками, указывающими так или иначе, затрудняют понимание указателей. Это делает их похожими на некоторые абстрактные, таинственные сущности. Они не.
Как и все остальное в вашем компьютере, указатели являются числами . Название «указатель» - это просто причудливый способ сказать «переменная, содержащая адрес».
Поэтому позвольте мне все перемешать, объяснив, как на самом деле работает компьютер.
У нас есть int, у него есть имя iи значение 5. Это хранится в памяти. Как и все, что хранится в памяти, ему нужен адрес, иначе мы не сможем его найти. Допустим, iзаканчивается по адресу 0x12345678 и его приятель jсо значением 6 заканчивается сразу после него. Предполагая, что 32-битный процессор, где int составляет 4 байта, а указатели - 4 байта, переменные сохраняются в физической памяти следующим образом:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Теперь мы хотим указать на эти переменные. Мы создаем один указатель на int int* ip1и один int* ip2. Как и все в компьютере, эти переменные-указатели также размещаются в памяти. Предположим, что они заканчиваются на следующих соседних адресах в памяти, сразу после j. Мы устанавливаем указатели для хранения адресов ранее выделенных переменных: ip1=&i;(«скопировать адрес i в ip1») и ip2=&j. Что происходит между строк:
Address Data Meaning
0x12345680 12 34 56 78 // The variable ip1(equal to address of i)
0x12345684 12 34 56 7C // The variable ip2(equal to address of j)
Итак, мы получили всего лишь 4 байтовых блока памяти, содержащих числа. Там нет мистических или магических стрел нигде в поле зрения.
Фактически, просто глядя на дамп памяти, мы не можем определить, содержит ли адрес 0x12345680 intили int*. Разница в том, как наша программа использует содержимое, хранящееся по этому адресу. (Задача нашей программы - просто сказать процессору, что делать с этими числами.)
Затем мы добавляем еще один уровень косвенности с int** ipp = &ip1;. Опять же, мы просто получаем кусок памяти:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
Шаблон кажется знакомым. Еще один фрагмент из 4 байтов, содержащий число.
Теперь, если бы у нас был дамп памяти вышеупомянутого вымышленного небольшого ОЗУ, мы могли бы вручную проверить, куда указывают эти указатели. Мы посмотрим, что хранится по адресу ippпеременной, и найдем содержимое 0x12345680. Который, конечно, адрес, где ip1хранится. Мы можем перейти по этому адресу, проверить его содержимое и найти адрес i, а затем, наконец, мы можем перейти по этому адресу и найти номер 5.
Поэтому, если мы возьмем содержимое ipp, *ippмы получим адрес переменной указателя ip1. Написав, *ipp=ip2мы копируем ip2 в ip1, это эквивалентно ip1=ip2. В любом случае мы бы получили
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(Эти примеры были приведены для процессора с прямым порядком байтов)
ippпри определении, чтобы ваш вопрос был