Está en la página 1de 11

2010

UNAN LEON Departamento de Computacin Ing. En Sistemas Sabatino Autor: Ing: Karina Esquivel Alvarado. Asignatura: Algoritmo y Estructura de Datos.

PUNTEROS (APUNTADORES)

Punteros

TEMA 4: PUNTEROS (APUNTADORES)


4.1 INTRODUCCIN

Los punteros en C tienen la fama, en el mundo de la programacin, de dificultad, tanto en el aprendizaje como en su uso. El puntero, no es ms que una herramienta muy potente que puede utilizar en sus programas para hacerlos ms eficiente y flexibles. Los punteros son, sin gnero de dudas, una de las razones fundamentales para que el lenguaje C sea tan potente y tan utilizado. Una variable(o puntero, como se llama normalmente) es una variable que contiene direcciones de otras variables. Todas las variables vistas hasta este momento contienen valores de datos, por el contrario las variables punteros contienen valores que son direcciones de memoria donde se almacenan datos. En resumen, un puntero es una variable que contiene una direccin de memoria, y utilizando punteros su programa puede realizar muchas tareas que no sera posible utilizando tipos de datos estndar. 4.2 DIRECCIONES DE MEMORIA

Cuando una variable se declara, se asocian tres atributos fundamentales con la misma: su nombre, su tipo y su direccin en memoria.

Esta caja representa la posicin de almacenamiento en memoria. El nombre de la variable est a la izquierda de la caja, la direccin de variable est encima de la caja y el tipo de variable est debajo en la caja. Si el valor de la variable se conoce, se representa en el interior de la caja int

Al valor de una variable se accede por medio de su nombre. Por ejemplo, se puede imprimir el valor de n con la sentencia: printf("%d",n); A la direccin de la variable se accede por medio del operador de direccin &. Por ejemplo, se puede imprimir la direccin de n con la sentencia: printf ("%p", &n);

Punteros

El operador de direccin "&" opera (se aplica) sobre el nombre de la variable para obtener sus direcciones. Ejemplo #1: //Obtiene el valor y la direccin de una variable //direccion.c #include<stdio.h> void main() { int n=35; printf("n=%d\n",n); printf("La direccion de &n=%p",&n); } Salida:

4.3

CONCEPTO DE PUNTERO

Cada vez que se declara una variable C, el compilador establece un rea de memoria para almacenar el contenido de la variable. Cuando se declara una variable int (entera), por ejemplo, el compilador asigna dos bytes de memoria. El espacio para esa variable se sita en una posicin especfica de la memoria, conocida como direccin de memoria. Cuando se referencia (se hace uso) al valor de la variable, el compilador de C accede automticamente a la direccin de memoria donde se almacena el entero. Se puede ganar en eficacia en el acceso a esta direccin de memoria utilizando un puntero. Cada variable que se declara en C tiene una direccin asociada con ella. Un puntero es una direccin de memoria. El concepto de punteros tiene correspondencia en la vida diaria. Cuando se enva una carta por correo, su informacin se entrega basada en un puntero que es la direccin de esa carta. Cuando se telefonea a una persona, se utiliza un puntero (el nmero de telfono que se marca). As pues, una direccin de correos y un nmero de telfono tienen en comn que ambos indican dnde encontrar algo. Son punteros a edificios y telfonos, respectivamente. Un puntero en C tambin indica dnde encontrar algo, dnde encontrar los datos que estn asociados con una variable? Un puntero C es la direccin de una Variable. Los punteros se rigen por estas reglas bsicas: un puntero es una variable como cualquier otra; variable puntero contiene una direccin que apunta a otra posicin en memoria; en esa posicin se almacenan los datos a los que apunta el puntero; un puntero apunta a una variable de memoria.

Punteros

Ejemplo #2: //Obtiene el valor y la direccin de una variable utilizando punteros #include <stdio.h> void main() { int n = 75; int *p=&n; //p variable puntero, tiene direccin de n printf("n = %d, &n= %p, p= %p\n",n,&n,p); printf ("&p = %p\n",&p); } Salida:

La variable p se denomina puntero debido a que su valor apunta a la posicin de otro valor. Es un puntero int cuando el valor al que apunta es de tipo int. 4.4 DECLARACIN DE PUNTEROS

Al igual que cualquier variable, las variables punteros han de ser declaradas antes de utilizarlas. La declaracin de una variable puntero debe indicar al compilador el tipo de dato al que apunta el puntero; para ello se hace preceder a su nombre con un asterisco (*), mediante el siguiente formato: <tipo de dato apuntado> *<identificador de puntero>; Algunos ejemplos de variables punteros: int *ptr1; /* Puntero a un tipo de dato entero (int)*/ long *ptr2; /* Puntero a un tipo de dato entero largo (long int)*/ char *ptr3; /* Puntero a un tipo de dato char * / float *f; /* Puntero a un tipo de dato float * / Un operador * en una declaracin indica que la variable declarada almacenar una direccin de un tipo de dato especificado. La variable ptr1 almacenar la direccin de un entero, la variable ptr2 almacenar la direccin de un dato tipo long, etc. Recuerda: Siempre que aparezca un asterisco (*) en una definicin de una variable, sta es una variable puntero. 4.5 INICIALIZACIN DE PUNTEROS

AI igual que otras variables, C no inicializa los punteros cuando se declaran y es preciso inicializarlos antes de su uso. La inicializacin de un puntero proporciona a ese puntero la direccin del dato correspondiente. Despus de la inicializacin, se puede utilizar el puntero

Punteros

para referenciar los datos direccionados. Para asignar una direccin de memoria a un puntero se utiliza el operador de referencia &. As, por ejemplo: &valor

Significa la direccin de valor. Por consiguiente, el mtodo de inicializacin (iniciacin), tambin denominado esttico, requiere: Asignar memoria (estticamente) definiendo una variable y a continuacin hacer que el puntero apunte al valor de la variable. int i=10; / * define una variable i * / int *p; / * define un puntero a un entero p*/ p = &i; /* asLgnd la direccin de i a p * / Asignar un valor a la direccin de memoria. *p = 50; Cuando ya se ha definido un puntero, el asterisco delante de la variable puntero indica <<el contenido de>> de la memoria apuntada por el puntero y ser del tipo dado. Este tipo de inicializacin es esttica, ya que la asignacin de memoria utilizada para almacenar el valor es fijo y no puede desaparecer. Una vez que la variable se define, el compilador establece suficiente memoria para almacenar un valor del tipo de dato dado. La memoria permanece reservada para esta variable y no se puede utilizar para otra cosa durante la ejecucin del programa. En otras palabras, no se puede liberar la memoria reservada para una variable. El puntero a esa variable se puede cambiar, pero permanecer la cantidad de memoria reservada. El operador & devuelve la direccin de la variable a la cual se aplica, Otros ejemplos de inicializacin estticos: 1. int edad = 50; /*define una variable edad de valor 50 */ int *p_edad = &edad; /*define un puntero de enteros inicializndolo con la direccin de edad */ 2. char *p; char alfa = 'A'; p = &alfa; 3. char cd[] = "Compacto'; char *c; c = cd; /*c tiene la direccin de Ia cadena cd * / Es un error asignar un valor, a un contenido de una variable puntero si previamente no se ha inicializado con la direccin de una variable, o bien se le ha asignado dinmicamente memoria. Por ejemplo: float *px; /*puntero a float */ *px = 23.5; /*error, px no contiene direccin*/

Punteros

Existe un segundo mtodo para inicializar un puntero, es mediante asignacin dinmica de memoria. Este mtodo utiliza las funciones de asignacin de memoria malloc( ),calloc( ),realloc( ) y free(). 4.6 INDIRECCIN DE PUNTEROS

Despus de definir una variable puntero, el siguiente paso es inicializar el puntero y utilizarlo para direccionar algn dato especfico en memoria. El uso de un puntero para obtener el valor al que apunta, es decir, su dato apuntado se denomina indireccionar el puntero (desreferencia- el puntero); para ello, se utiliza el operador de indireccin * . int edad; int* p_edad; p_edad= &edad; *p_edad= 50; Si se desea imprimir el valor de edad: printf("%d",edad;) /*imprime el valor de edad * / Tambin se puede imprimir el valor de edad dereferenciando el puntero a edad: printf("%d,*p_edad) ; /*indirecciona p_edad * / Ejemplo #3: /*El listado del siguiente programa muestra el concepto de creacin, inicializacin e indireccin de una variable puntero*/ #include <stdio.h> char c; /*variable global de tipo carcter*/ void main() { char *pc; //un puntero a una variable carcter pc = &c; for(c ='A';c<='Z';c++) printf ("%c - ",*pc) ; } Salida:

La ejecucin de este programa visualiza el alfabeto. La variable puntero pc es un puntero a una variable carcter. La lnea pc=&c asigna a pc la direccin de la variable c(&c). El bucle for almacena en c las letras del alfabeto y la sentencia printf( "%c",*pc ) ; visualiza el contenido de la variable apuntada por pc; c y pc se refieren a la misma posicin en memoria. Si la variable c , que se almacena en cualquier parte de la memoria, y pc , que apunta a esa misma posicin,

Punteros

se refiere a los mismos datos, de modo que el cambio de una variable debe afectar a la otra; pc y c se dice que son alias, debido a que pc acta como otro nombre de c. 4.7 OPERADORES DE PUNTEROS

4.8

PUNTEROS Y VERIFICACIN DE TIPOS

Los punteros se enlazan a tipos de datos especficos, de modo que C verificar si se asigna la direccin de un tipo de dato al tipo correcto de puntero. As, por ejemplo, si se define un puntero a float, no se le puede asignar la direccin de un carcter o un entero. Por ejemplo, este segmento de cdigo no funcionar: float *fp; char c; fp = &c; / * no es vlido * / C no permite la asignacin de la direccin de c a f p, ya que f p es una variable puntero que apunta a datos de tipo real, float. C requiere que las variables puntero direccionen realmente variables del mismo tipo de dato que est ligado a los punteros en sus declaraciones. 4.9 PUNTEROS NULL Y VOID

Normalmente un puntero inicializado adecuadamente apunta a alguna posicin especfica de la memoria. Sin embargo, un puntero no inicializado, como cualquier variable, tiene un valor aleatorio hasta que se inicializa el puntero. En consecuencia, ser preciso asegurarse que las variables puntero utilicen direcciones de memoria vlida. Existen dos tipos de punteros especiales muy utilizados en el tratamiento de sus programas: los punteros void y null (nulo). Un puntero nulo no apunta a ninguna parte (dato vlido) en particular, es decir, un puntero nulo no direcciona ningn dato vlido en memoria. Un puntero nulo se utiliza para proporcionar a un programa un medio de conocer cuando una variable puntero no direcciona a un dato vlido. Para declarar un puntero nulo se utiliza la macro NULL, definida en los archivos de cabecera stdef.h, stdio.h, stdlib.h y string.h. Se debe incluir uno o ms de estos archivos de cabecera antes de que se pueda utilizar la macro NULL. Ahora bien, se puede definir NULL en la parte superior de su programa (o en un archivo de cabecera personal) con la lnea:

Punteros

#define NULL O Un sistema de inicializar una variable puntero a nulo es: char *p = NULL;

Algunas funciones C tambin devuelven el valor NULL si se encuentra un error. Se pueden aadir test para el valor NULL comparando el puntero con NULL: char *p; p = malloc(121 * sizeof(char)); if (p == NULL) puts ("Error de asignacin de memoria") ; Nunca se utiliza un puntero nulo para referenciar un valor. Los punteros nulos se utilizan en un test condicional para determinar si un puntero se ha inicializado. Los punteros nulos se utilizan con frecuencia en programas con arrays de punteros. Cada posicin del array se inicializa a NULL; despus se reserva memoria dinmicamente y se asigna a la posicin correspondiente del array, la direccin de la memoria. En C se puede declarar un puntero de modo que apunte a cualquier tipo de dato, es decir, no se asigna a un tipo de dato especfico. El mtodo es declarar el puntero como un puntero void *, denominado puntero genrico. void *ptr; / * declara un puntero void, punLero genrico * / El puntero ptr puede direccionar cualquier posicin en memoria, pero el puntero no est unido a un tipo de dato especfico. De modo similar, los punteros void pueden direccionar una variable float, una char, o una posicin arbitraria o una cadena. Recuerde: No confundir punteros void y NULL. Un puntero nulo no direcciona ningn dato vlido. Un puntero void direcciona datos de un tipo no especificado. Un puntero void se puede igualar a nulo si no se direcciona ningn dato vlido. Nulo es un valor; void es un tipo de dato.

Punteros

4.10

PUNTEROS A PUNTEROS

Un puntero puede apuntar a otra variable puntero. Este concepto se utiliza con mucha frecuencia en programas complejos de C. Para declarar un puntero a un puntero se hace preceder a la variable con dos asteriscos (**).

La declaracin de un puntero a puntero se realiza de la siguiente manera: tipo **nombre_puntero; En el ejemplo siguiente ptr5 es un puntero a un puntero. int valor_e = 100; int *ptr1 = &valor_e; int **ptr5 = &ptr1; ptri y ptr5 son punteros. Ptr1 apunta a la variable valor_e de tipo int. ptr5 contiene la direccin de ptr1. Se puede asignar valores a valor_e con cualquiera de las sentencias siguientes: valor_e = 95; *ptrl= 105; **ptr5 = 99; 4.11 / * Asigna 105 a valor_e* / / * Asignd 99 a valor_e * /

PUNTEROS Y ARRAYS

Los arrays y punteros estn fuertemente relacionados en el lenguaje C. Se pueden direccionar arrays como si fueran punteros y punteros como si fueran arrays. La posibilidad de almacenar y acceder a punteros y arrays, implica que se pueden almacenar cadenas de datos en elementos de arrays. Sin punteros eso no es posible, ya que no existe el tipo de dato cadena en C. No existen variables de cadena. nicamente constantes de cadena.

Punteros

4.11.1 NOMBRES DE ARRAYS COMO PUNTEROS Un nombre de un array es simplemente un puntero. Supongamos que se tiene la siguiente declaracin de un array: int lista [5] = {10,20,30,40,50};

Si se manda visualizar lista[O] se visualizar 10. Pero, qu suceder si se manda visualizar *lista? Como un nombre de un array es un puntero, tambin se ver 10. Esto significa que: lista+O apunta a lista[O] lista+1 apunta a lista[1] lista+2 apunta a lista[2] lista+3 apunta a lista[3] lista+4 apunta a lista[4] Por consiguiente, para imprimir (visualizar), almacenar o calcular un elemento de un array, se puede utilizar notacin de subndices o notacin de punteros. Dado que un nombre de un array contiene la direccin del primer elemento del array, se debe indireccionar el puntero para obtener el valor del elemento. El nombre de un array es un puntero, contiene la direccin en memoria de comienzo de la secuencia de elementos que forma el array. Es un puntero constante ya que no se puede modificar, slo se puede acceder para indexar a los elementos del array. En el ejemplo se pone de manifiesto operaciones correctas y errneas con nombres de array. float v[10]; float *p; floa x = 100.5; int j; /* se indexa a partir de v * / for (j= 0; j<10; j++) *(v+j) = j*10.0; p = v+4; /*se asigna la direccin del quinto elemento*/ v = &x; /*error: intento de modificar un puntero constante */

10

Punteros

4.11.2 VENTAJAS DE LOS PUNTEROS Un nombre de un array es una constante puntero, no una variable puntero. No se puede cambiar el valor de un nombre de array, como no se pueden cambiar constantes. Esto explica por qu no se pueden asignar valores nuevos a un array durante una ejecucin de un programa. Por ejemplo, si cnombre es un array de caracteres, la siguiente sentencia no es vlida en C: cnombre = "Mi Nicaragua"; Se pueden asignar valores al nombre de un array slo en el momento de la declaracin, o bien utilizando funciones, tales como (ya se ha hecho anteriormente) strcpy( ) . Se pueden cambiar punteros para hacerlos apuntar a valores diferentes en memoria. El siguiente programa muestra como cambiar punteros. El programa define dos valores de coma flotante. Un puntero de coma flotante apunta a la primera variable v1 y se utiliza en printf(). El puntero se cambia entonces, de modo que apunta a la segunda variable de coma flotante v2. #include <stdio.h> int main() { float v1 = 756.423; float v2 = 900.545; float *p_v; p_v = &v1; printf ("El primer valor es %f \n",* p_v) ; //se imprime 756.423 p_v = &v2; printf("E1 segundo valor es %f\n",* p_v) ; //se imprime 900.545 return 0; } Salida:

Por esta facilidad para cambiar punteros, la mayora de los programadores de C utilizan punteros en lugar de arrays. Como los arrays son fciles de declarar, los programadores declaran arrays y a continuacin utilizan punteros para referencia a los elementos de dichos arrays.

11

También podría gustarte