martes, 5 de marzo de 2013

Una nota sobre los punteros

Volviendo a practicar con C, y nos volvemos a encontrar las míticas criaturas llamadas "punteros" del lenguaje C, esas siniestras y crueles seres que confunden y aterran al programador nuevo.

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:

type *ptr
"un puntero "type" llamado  ptr"
*ptr
"El valor de lo que sea que ptr apunta"
*(ptr + i)
"el valor de lo que sea que ptr apunta + i"
&thing
"la direccion de thing"
type *ptr = &thing
"un puntero type llamado ptr inicializado a la direccion de thing"
ptr++
"incrementar donde ptr apunta"

No hay comentarios:

Publicar un comentario