Minha opinião pessoal é que as figuras com setas apontando dessa maneira ou dificultam a compreensão dos ponteiros. Faz com que pareçam algumas entidades abstratas e misteriosas. Eles não são.
Como tudo no seu computador, ponteiros são números . O nome "ponteiro" é apenas uma maneira elegante de dizer "uma variável que contém um endereço".
Portanto, deixe-me agitar as coisas explicando como um computador realmente funciona.
Temos um int, ele tem o nome ie o valor 5. Isso é armazenado na memória. Como tudo armazenado na memória, ele precisa de um endereço ou não poderíamos encontrá-lo. Digamos que itermina no endereço 0x12345678 e seu amigo jcom o valor 6 acaba logo após ele. Supondo que uma CPU de 32 bits em que int seja 4 bytes e ponteiros sejam 4 bytes, as variáveis são armazenadas na memória física como esta:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Agora queremos apontar para essas variáveis. Criamos um ponteiro para int int* ip1, e um int* ip2. Como tudo no computador, essas variáveis de ponteiro também são alocadas em algum lugar da memória. Vamos supor que eles acabem nos próximos endereços adjacentes na memória, imediatamente após j. Definimos os ponteiros para conter os endereços das variáveis alocadas anteriormente: ip1=&i;("copie o endereço de i para ip1") e ip2=&j. O que acontece nas entrelinhas é:
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)
Então, o que obtivemos foram apenas alguns pedaços de 4 bytes de memória contendo números. Não há flechas místicas ou mágicas em nenhum lugar à vista.
De fato, apenas olhando para um despejo de memória, não podemos dizer se o endereço 0x12345680 contém um intou int*. A diferença é como o nosso programa escolhe usar o conteúdo armazenado neste endereço. (A tarefa do nosso programa é realmente apenas dizer à CPU o que fazer com esses números.)
Então adicionamos mais um nível de indireção com int** ipp = &ip1;. Novamente, temos apenas um pedaço de memória:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
O padrão parece familiar. Ainda outro pedaço de 4 bytes contendo um número.
Agora, se tivéssemos um despejo de memória da pequena RAM fictícia acima, poderíamos verificar manualmente onde esses ponteiros apontam. Examinamos o que está armazenado no endereço da ippvariável e encontramos o conteúdo 0x12345680. Qual é, obviamente, o endereço onde ip1está armazenado. Podemos ir para esse endereço, verificar o conteúdo e encontrar o endereço de i; finalmente, podemos ir para esse endereço e encontrar o número 5.
Portanto, se pegarmos o conteúdo de ipp, *ippobteremos o endereço da variável ponteiro ip1. Ao escrever *ipp=ip2copiamos ip2 para ip1, é equivalente a ip1=ip2. Em ambos os casos, teríamos
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(Estes exemplos foram dados para uma grande CPU endian)
ippquando defini-lo, assim que sua pergunta é completo ;-)