Мое личное мнение заключается в том, что фотографии со стрелками, указывающими этот путь, или которые затрудняют понимание указателей. Это заставляет их казаться абстрактными, таинственными сущностями. Они не.
Как и все остальное на вашем компьютере, указатели - numbers . Имя «указатель» - просто причудливый способ сказать «переменная, содержащая адрес».
Поэтому позвольте мне разобраться, объясняя, как работает компьютер.
Мы имеют 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*
. Разница заключается в том, как наша программа выбирает использование содержимого, хранящегося по этому адресу. (Задача нашей программы состоит в том, чтобы просто сказать CPU, что делать с этими числами.)
Затем добавим еще один уровень косвенности с 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
(Эти примеры были приведены для большого центрального процессора)