Entonces ¿por que están implementadas?, ¿Para que sirven?, bueno en realidad los Punteros, es algo sencillo, los estúpidos y ridículos usos que les dan es lo que espanta a la gente.
¿Que son?, cuando tienes un arreglo, digamos array[i], tenemos el arreglo "array" y su indicie, llamado 'i' por la misma razón, si el valor de i es 0 entonces obtenemos el valor en array[0], si el indice es 1, entonces obtenemos el valor en array[1].
Si 'i' es el indice, y el indice es la dirección en donde esta la información del arreglo, entonces el Arreglo como tal, es un conjunto de direcciones, pero localizadas en la memoria de la maquina, y los indices de un arreglo, nos dicen en que parte de la maquina esta.
Esto permite a C pensar en tu computadora como si fuera un enorme arreglo de bytes, un montón de espacio en memoria para ser acomodados.
A todo esto, ¿Que son?, bueno un puntero, es un "apuntador" a esa direccion en memoria, los punteros no almacenan nada, solo "apuntan" a donde esta, imaginemos que tu arreglo es un librero, y quieres el libro que esta en libros[3][2], vas a esa dirección y lo tomas, un puntero seria como la ficha bibliográfica te dice en donde esta, en que parte esta, sin embargo NO ES el libro, solo te dice donde esta.
Recuerda este proceso que pasa cuando asignas un puntero:
-Tu computadora crea un bloque de memoria en si misma, que representa al arreglo
-"Apuntamos" el inicio de ese bloque de memoria
-Se usa el "indice", que en este caso es Array[i], para obtener el elemento en una parte del bloque de memoria
-el puntero esta "apuntando" al inicio del bloque de memoria, si queremos obtener el mismo dato tenemos que hacer puntero+i, osea mueve el puntero i posiciones.
C sabe a donde apunta el puntero, sabe que tipo de datos es a lo que apunta, el tamaño de esos datos y como obtenerte esos datos. Pero al igual que los arreglos, los punteros pueden ser "modificados", sin embargo el puntero NO ES otro arreglo, es el mismo arreglo, así que si modificas un puntero, terminaras modificando el arreglo original, aquí es donde la gente tiene problemas.
Imagina que tienes el arreglo:
char *Caminantes[] = {"Jace","Chandra","Garruck","Ajani", "Liliana"}
, creamos un puntero
char *puntero_caminates = Caminantes;
agregamos un caminante
Caminantes.add("Karn") //No es la sintaxis correcta, pero me entienden
nuestro arreglo queda como
Caminantes ={"Jace","Chandra","Garruck","Ajani", "Liliana","Karn"}
que pasa si hacemos
puntero_caminates.add("Tezzert");
Tezzert es agregado,PERO al arreglo de caminantes, no en puntero, por que no es un arreglo
asi que tenemos
Caminantes ={"Jace","Chandra","Garruck","Ajani", "Liliana","Karn", "Tezzeret"}
Los punteros tienen varios usos prácticos:
-Le pides al sistema operativo trabajar con el bloque de memoria creado, incluso funciona con struct y strings
-Pasar grandes bloques de memoria a funciones con punteros para no tener que pasar todo.
Digamos que tienes que pasar un bloque de 200 megas, si quieres "pasarlo" de manera normal, tendrías que crear una variable para almacenarla, así que la computadora reservaría otros 200 megas, el del arreglo normal y el del arreglo nuevo, y si es una estructura que tienes que estar pasando entre funciones es muy desgastante en memoria. Con un puntero sin embargo solo pasas el "AHI ESTA" y no creas nada adicional.
-Tomar la dirección de una función para hacer llamadas dinámicas
Los punteros te van a mostrar como esta ese bloque de memoria en ese momento, así que si fue afectado por algún otra forma puedes obtener ese bloque con un puntero,
-ACompleto analizis de un bloque de memoria para convertir los bytes de un puerto de red en estructura de datos o convertirlo a archivo
Para cualquier otro uso, se deberían usar arreglos, antes los punteros se usaban con mucha frecuencia por que el compilador no optimizaba los arreglos de forma efectiva, así que tener 1 o 2 arreglos nuevos alentaba mucho tu programa, ahora ya no es el caso.
Syntaxis de los puntero
Como nota adicional: