Mi opinión muy personal es que las imágenes con flechas apuntando hacia este lado o que hacen que los punteros sean más difíciles de entender. Los hace parecer algunas entidades abstractas y misteriosas. Ellos no son.
Como todo lo demás en su computadora, los punteros son números . El nombre "puntero" es solo una forma elegante de decir "una variable que contiene una dirección".
Por lo tanto, déjenme remover las cosas explicando cómo funciona realmente una computadora.
Tenemos un int
, tiene el nombre i
y el valor 5. Esto se almacena en la memoria. Como todo lo que está almacenado en la memoria, necesita una dirección, o no podríamos encontrarla. Digamos que i
termina en la dirección 0x12345678 y su amigo j
con valor 6 termina justo después. Suponiendo una CPU de 32 bits donde int es de 4 bytes y los punteros son de 4 bytes, las variables se almacenan en la memoria física de esta manera:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Ahora queremos señalar estas variables. Creamos un puntero a int int* ip1
, y one int* ip2
. Como todo en la computadora, estas variables de puntero también se asignan en algún lugar de la memoria. Supongamos que terminan en las siguientes direcciones adyacentes en la memoria, inmediatamente después j
. Configuramos los punteros para que contengan las direcciones de las variables previamente asignadas: ip1=&i;
("copie la dirección de i en ip1") y ip2=&j
. Lo que sucede entre líneas es:
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)
Entonces, lo que obtuvimos fueron aún algunos fragmentos de memoria de 4 bytes que contenían números. No hay flechas místicas o mágicas a la vista.
De hecho, con solo mirar un volcado de memoria, no podemos saber si la dirección 0x12345680 contiene un int
o int*
. La diferencia es cómo nuestro programa elige usar los contenidos almacenados en esta dirección. (La tarea de nuestro programa es en realidad decirle a la CPU qué hacer con estos números).
Luego agregamos otro nivel de indirección con int** ipp = &ip1;
. De nuevo, solo tenemos un trozo de memoria:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
El patrón parece familiar. Otro trozo de 4 bytes que contiene un número.
Ahora, si tuviéramos un volcado de memoria de la pequeña RAM ficticia anterior, podríamos comprobar manualmente dónde apuntan estos punteros. Echamos un vistazo a lo que está almacenado en la dirección de la ipp
variable y encontramos los contenidos 0x12345680. Cuál es, por supuesto, la dirección donde ip1
se almacena. Podemos ir a esa dirección, verificar el contenido allí y encontrar la dirección de i
, y finalmente podemos ir a esa dirección y encontrar el número 5.
Entonces, si tomamos el contenido de ipp, *ipp
obtendremos la dirección de la variable de puntero ip1
. Al escribir *ipp=ip2
, copiamos ip2 en ip1, es equivalente a ip1=ip2
. En cualquier caso obtendríamos
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(Estos ejemplos se dieron para una gran CPU endian)
ipp
cuando lo defina, para que su pregunta esté completa ;-)