Vous êtes sur la page 1sur 4

Una variable es declarada dndole un tipo y un nombre (por ejemplo: int k;) Una variable apuntador es declarada dndole

un tipo y un nombre (por ejemplo: int *ptr) en donde el asterisco le dice al compilador que la variable de nombre ptr es una variable apuntador. Y el tipo le dice al compilador a qu tipo de variable va a apuntar nuestro apuntador (int en este caso). Una vez que una variable ha sido declarada, podemos obtener su direccin anteponiendo a su nombre el operador unitario &, como en &k. Podemos indireccionar un apuntador, es decir, hacer referencia al valor contenido en la direccin a la que apunta, usando el operador *, como en *ptr. Consideremos el porqu tenemos que identificar el "tipo" de variable a la que apunta un puntero como en: int *ptr; Una de las razones para hacer esto es que una vez que ptr apunta a algo y si escribimos: *ptr = 2; El compilador sabr cuantos bytes va a reservar a la posicin de memoria a la que apunta ptr. Si ptr fuera declarado como un puntero a entero, se reservaran 4 bytes. De modo similar para nmeros de punto flotante (float) y enteros dobles (doubles), se copiara el nmero apropiado de bytes. Por ejemplo, consideremos un bloque de memoria para almacenar 10 nmeros enteros en un arreglo. Eso es 40 bytes de memoria reservados para colocar 10 enteros. Digamos que ahora apuntamos nuestro apuntador entero ptr al primero de estos nmeros enteros. Es ms, supongamos que este primer entero est almacenado en la posicin de memoria 100. Entonces que pasa cuando escribimos: ptr + 1; Ya que el compilador sabe que este es un apuntador (que su valor es una direccin de memoria) y que apunta a un entero (su direccin actual: 100, es la direccin donde se aloja un entero), aade 4 a ptr en lugar de 1, as que ptr apunta al siguiente entero, en la posicin de memoria 104. Similarmente, si ptr fuera declarado como apuntador a entero corto, aadira 2 en lugar de 1. Lo mismo va para los otros tipos de datos como flotantes, dobles o an tipos definidos por el usuario como estructuras. No se trata obviamente del tipo normal de adicin a la que estamos acostumbrados. En C, se le conoce como adicin usando aritmtica de punteros. Igualmente, como ++ptr y ptr++ son equivalentes a ptr + 1. Incrementar un apuntador usando el operador unitario de incremento ++, ya sea antes o despues, incrementa la direccin por la cantidad sizeof (tipo) donde tipo es el tipo de objeto al que se apunta (por ejemplo 4 si se trata de un entero). Y ya que un bloque de 10 enteros acomodados contiguamente en la memoria es, por definicin, un arreglo de enteros, esto nos revela una interesante relacin entre arreglos y apuntadores. Consideremos lo siguiente: int arreglo[] = {1,23,17,4,-5,100}; Tenemos entonces un arreglo conteniendo seis enteros. Nos referimos a cada uno de estos enteros por medio de un subndice a arreglo, es decir usando arreglo[0] hasta arreglo[5]. Pero podemos acceder a ellos de un modo alternativo usando un puntero de esta manera:
int *ptr; /* inicializamos el puntero al primer entero de nuestro arreglo* ptr = &arreglo[0];

Y entonces podemos imprimir los valores de nuestro arreglo, ya sea usando la notacin de arreglos o indireccionando nuestro puntero. El siguiente cdigo ilustra este concepto.
#include <stdio.h> int arreglo[] = {1,23,17,4,-5,100}; int *ptr; int main(void) { int i; /* incializamos nuestro puntero al primer elemento del arreglo*/ ptr = &arreglo[0]; printf("\n\n"); for (i = 0; i < 6; i++) { printf("arreglo[%d] = %d ", i, arreglo[i]); printf("ptr + %d = %d\n",i, *(ptr + i)); } getch(); }

/*<-- A */ /*<-- B */

Compilen y ejecuten el programa de arriba y noten como las lneas marcadas con A y B imprimen los mismos valores. Observen como indireccionamos nuestro puntero ptr en la lnea B, primero le aadimos i y luego indireccionamos el nuevo apuntador. Prueben cambiar la lnea B de tal modo que quede:
printf ("ptr + %d = %d\n", i, *ptr++);

Ahora compilen y ejecuten de nuevo, y luego vuelvan a modificarla por:


printf(ptr + %d = %d\n, i, *(++ptr));

Una vez ms, compilemos y ejecutemos. Traten de predecir lo que saldr a pantalla cada vez y revisen con cuidado la salida real. En C se establece que donde usemos &nombre_del_arreglo[0] podemos reemplazarlo con nombre_del_arreglo, esto en el cdigo de ejemplo lo que escribimos como: ptr = &mi_arreglo[0]; podemos escribirlo como: ptr = mi_arreglo;y obtenemos el mismo resultado. Esto conduce a decir que el nombre de un arreglo es un apuntador. Si bien esto es cierto, tambin podemos definir que el nombre de un arreglo es la direccin del primer elemento que contiene el arreglo. Muchos principiantes (incluyndome a mi cuando estuve aprendiendo) muestran tendencia a confundirse pensando en el como un puntero. Por ejemplo, si bien podemos hacer ptr = arreglo; no podemos hacer: arreglo = ptr; La razn es que mientras ptr es una variable, arreglo es una constante. Esto es, la direccin en la que el primer elemento de mi_arreglo ser almacenado no puede ser cambiado una vez que mi_arreglo[] ha sido declarado. Modifiquemos el programa de ejemplo cambiando: ptr = &mi_arreglo [0]; por ptr = mi_arreglo; ejecuten de nuevo para verificar que los resultados son idnticos. Punteros y Cadenas En C, las cadenas son arreglos de caracteres. Esto no es necesariamente cierto para otros lenguajes. En Basic, Pascal, Fortran y en otros lenguajes, una cadena tiene definido su propio tipo de datos. Pero en C, esto no es as. En C una cadena es un arreglo de caracteres terminado con un carcter binario de cero (escrito como \0).

Escribamos algo de cdigo, el cual si bien es referido por propsitos meramente ilustrativos, probablemente no lo escribiremos en un programa real. Consideremos por ejemplo: char mi_cadena[40]; mi_cadena [0] = c; mi_cadena [1] = l; mi_cadena [2] = a: mi_cadena [3] = s: mi_cadena [4] = e: mi_cadena[5] = \0; Nosotros nunca construiramos cadenas de este modo, el resultado final es una cadena que es en realidad un arreglo de caracteres terminado con un caracter nul. Por definicin, en C, una cadena es un arreglo de caracteres terminado con el carcter nul. Hay que tener cuidado con que nul no es lo mismo que NULL. El nul se refiere a un cero definido por la secuencia de escape \0. Esto es, que ocupa un byte de memoria. El NULL, por otra parte, es el nombre de la macro usada para inicializar apuntadores nulos. NULL est definido en un archivo de cabecera del compilador de C, mientras que nul puede no estar definido del todo. Ya que al estar escribiendo cdigo como el de arriba gastaramos mucho tiempo, C permite dos modos alternativos de llegar al mismo resultado. El primero sera escribir: char mi_cadena [40] = {c, l, a, s, e, \0,}; Pero se lleva ms tecleado del que es conveniente. As que C permite: char mi_cadena [40] = "clase"; Cuando usamos las comillas dobles, en lugar de las simples usadas en los ejemplos anteriores, el carcter nul (\0) se aade automticamente al final de la cadena. En cualquiera de los casos descritos arriba sucede la misma cosa. El compilador asigna un bloque continuo de memoria de 40 bytes de longitud para alojar los caracteres y los inicializa de tal manera que los primeros 6 caracteres son clase\0. #include <stdio.h> char cadA[80] = "Cadena a usar para el programa de ejemplo"; char cadB[80]; int main(void) { char *pA; /* un apuntador al tipo caracter */ char *pB; /* otro apuntador al tipo caracter */ printf("%s\n",cadA); /* muestra la cadena cadA de ejemplo */ pA = cadA; /* apunta pA a la cadena cadA */ printf("%s\n",pA); /* muestra a donde apunta pA */ pB = cadB; /* apunta pB a la cadena strB */ printf("\n"); /* dejamos una lnea en blanco */ while(*pA != '\0')/* linea A*/ { *pB++ = *pA++; /* linea B */ } *pB = '\0'; /* linea C */ printf("%s",cadB); /* muestra cadB en la pantalla */ getchar(); }

Lo que hicimos arriba fue comenzar por definir dos arreglos de 80 caracteres cada uno. Ya que estos son definidos globalmente, son inicializados a \0 primeramente. Luego cadA tiene sus primeros 42 caracteres inicializados a la cadena que est entre comillas. Ahora, yendo al cdigo, declaramos dos apuntadores a caracter y mostramos la cadena en pantalla. Despus apuntamos con el puntero pA a cadA. Esto quiere decir que, por el significado de la operacin de asignacin, copiamos la direccin de memoria de cadA[0] en nuestra variable apuntador pA. Usamos entonces printf para mostrar lo que estamos apuntando con pA en la pantalla. Consideremos aqu que el prototipo de la funcin puts() es:

Vous aimerez peut-être aussi