P. 1
Apuntadores en C y C++

Apuntadores en C y C++

|Views: 2|Likes:
Publicado porJ Israel Toledo

More info:

Published by: J Israel Toledo on Sep 09, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

05/25/2015

pdf

text

original

Apuntadores en C y C

++
Universidad de Carabobo Facultad Experimental de Ciencias y Tecnolog´ ıa Prof. Marcos A. Gil T. 8 de diciembre de 2004

1.

Introducci´ on

Los apuntadores en C y C++ son una herramienta muy potente de programaci´ on que suele causar mucha confusi´ on en los estudiantes que la est´ an aprendiendo. Adem´ as, cuando los programadores cometen un error en su utilizaci´ on, puede ser muy dif´ ıcil encontrar el error, por lo cual es importante saber utilizarlos muy bien. El uso de apuntadores en C y C++ es muy importante debido a que permite hacer los programas m´ as eficientes y m´ as flexibles. En en este art´ ıculo se explica de una manera sencilla y breve todo lo referente a la utilizaci´ on de apuntadores tanto en C como en C++. Todo lo explicado en este art´ ıculo aplica tanto para C como para C++, a menos que se especifique un lenguaje en particular. En algunos ejemplos de c´ odigo que son aplicables a C aparecen instrucciones de entrada y salida de las librer´ ıas est´ andar de C++.

2.

Definici´ on de apuntador

Cuando se declara una variable, el compilador reserva un espacio de memoria para ella y asocia el nombre de ´ esta a la direcci´ on de memoria desde donde comienzan los datos de esa variable. Las direcciones de memoria se suelen describir como n´ umeros en hexadecimal. Un apuntador es una variable cuyo valor es la direcci´ on de memoria de otra variable. Se dice que un apuntador “apunta” a la variable cuyo valor se almacena a partir de la direcci´ on de memoria que contiene el apuntador. Por ejemplo, si un apuntador p almacena la direcci´ on de una variable x, se dice que “p apunta a x ”.

3.

Referenciaci´ on

La referenciaci´ on es la obtenci´ on de la direcci´ on de una variable. En C y C++ esto se hace a trav´ es del operador ‘&’, aplicado a la variable a la cual se desea saber su direcci´ on. N´ otese que se trata de un operador unario. Ejemplo: C´ odigo C y C++ int x = 25; cout << "La direcci´ on de x es: " << &x << endl;

Este c´ odigo imprime un valor del estilo “0x4fffd34”. Este valor puede variar durante cada ejecuci´ on del programa, debido a que el programa puede reservar distintos espacios de memoria durante cada ejecuci´ on.

y. // A ’y’ se le asigna 20 C++ adem´ as provee el operador binario ‘->’. Desreferenciaci´ on de apuntadores La desreferenciaci´ on es la obtenci´ on del valor almacenado en el espacio de memoria donde apunta un apuntador. q = p. p = &i. *q. // Apuntador a un dato de tipo entero (int) char *cad1. En C y C++ esto se hace a trav´ es del operador ‘*’. y el nombre del apuntador. int *p. el operador ‘*’. Declaraci´ on de apuntadores Para declarar un apuntador se especifica el tipo de dato al que apunta. utilizado para obtener campos de un registro con un apuntador al mismo de una manera m´ as f´ acil y legible. p = &x. cout << "El valor de x es: " << *p << endl. // Apuntador a un dato de tipo punto-flotante (float) 5. Asignaci´ on de apuntadores Se pueden asignar a un apuntador direcciones de variables a trav´ es del operador de referenciaci´ on (‘&’) o direcciones almacenadas en otros apuntadores. *cad2. N´ otese que se trata de un operador unario. int *p. Muchos compiladores de C tambi´ en soportan este operador. // Dos apuntadores a datos de tipo car´ acter (char) float *ptr2. // Se le asigna a ’p’ la direcci´ on de ’i’ // Se le asigna a ’q’ la direcci´ on almacenada en ’p’ (la misma de ’i’) 6. Ejemplos: C´ odigo C y C++ int i = 5. aplicado al apuntador que contiene la direcci´ on del valor. Ejemplos: C´ odigo C y C++ int x = 17. // Imprime 17 y = *p + 3. Ejemplo: 2 .4. La sintaxis es la siguiente: <tipo de dato apuntado> *<indentificador del apuntador> A continuaci´ on se muestran varios ejemplos: C´ odigo C y C++ int *ptr1.

Verificaci´ on de tipos en apuntadores Al igual que el resto de las variables. // Esto no es v´ alido (el compilador genera un error) 8. // Incorrecto *p = 3.5. algunas veces es posible que un apuntador no contenga una direcci´ on v´ alida. (*pd). cout << "El valor apuntado por p es: " << *p << endl. // Esto es v´ alido p2 = &x. ya sea porque la variable asociada termina su ´ ambito o porque ese espacio de memoria fue reservado din´ amicamente y luego se liber´ o1 . hasta que se inicialice con alg´ un valor (direcci´ on). int edad. int x. Un apuntador puede contener una direcci´ on inv´ alida debido a dos razones: 1. un apuntador inicializado adecuadamente apunta a alguna posici´ on espec´ ıfica de la memoria. Ejemplo: 1 La asignaci´ on din´ amica de memoria se explica en la secci´ on 13 3 . Despu´ es de que un apuntador ha sido inicializado.’ pd->edad = 23. }. Ejemplo: C´ odigo C y C++ int *p1. Data d. la direcci´ on que posee puede dejar de ser v´ alida si se libera la memoria reservada en esa direcci´ on. en cuyo caso es incorrecto desreferenciarlo (obtener el valor al que apunta) porque el programa tendr´ a un comportamiento impredecible y probablemente err´ oneo. al igual que cualquier otra variable. Data *pd = &d. // Acceso al campo ’edad’ utilizando el operador ’.C´ odigo C++ struct Data { char nombre[20]. float *p2. p1 = &x. // Incorrecto 2. los apuntadores se enlazan a tipos de datos espec´ ıficos (apuntadores a variables de cierto tipo). de manera que a un apuntador s´ olo se le pueden asignar direcciones de variables del tipo especificado en la declaraci´ on del apuntador. // Acceso al campo ’edad’ utilizando el operador ’->’ 7. Cuando un apuntador se declara.edad = 23. Direcciones inv´ alidas y la direcci´ on NULL Normalmente. el mismo posee un valor cualquiera que no se puede conocer con antelaci´ on. Sin embargo. aunque es posible que funcione bien. Ejemplo: C´ odigo C y C++ float *p.

en C++ se encuentra disponible sin incluir ning´ un archivo de cabecera. y = *p. Apuntadores a apuntadores Dado que un apuntador es una variable que apunta a otra. matrices esparcidas. Si casualmente la direcci´ on es la misma de otra variable utilizada en el programa. o que el programa no responda y deje al sistema operativo inestable. en cuyo caso detiene abruptamente el programa. como las listas enlazadas. Esto puede ocasionar que el programa genere resultados incorrectos. NULL es una macro t´ ıpicamente definida en archivos de cabecera como stdef. por ejemplo. Estos 4 . y a su vez los segundos pueden apuntar a apuntadores. f´ acilmente se puede deducir que pueden existir apuntadores a apuntadores. p = &x. // Correcto *p = 23. Cuando no se desea que un apuntador apunte a algo.C´ odigo C y C++ int *p. // Incorrecto } Si se intenta desreferenciar un apuntador que contiene una direcci´ on inv´ alida pueden ocurrir cosas como las siguientes: Se obtiene un valor incorrecto en una o m´ as variables debido a que no fue debidamente inicializada la zona de memoria que se accede a trav´ es de la direcci´ on en cuesti´ on. // Correcto } void main() { func(). o est´ a dentro del rango de direcciones de una zona de memoria utilizada. Existe la posibilidad de que la direcci´ on est´ e fuera de la zona de memoria utilizada para almacenar datos y m´ as bien est´ e. El valor NULL es muy u ´til para la construcci´ on de estructuras de datos din´ amicas. Al intentar escribir en dicha zona. y = *p. En muchos casos el sistema operativo detecta el acceso inadecuado a una direcci´ on de memoria. en cuyo caso se dice que el apuntador es nulo (no apunta a nada). y tomar las medidas necesarias. Normalmente. 9.h. en la zona donde se almacenan las instrucciones del programa. f´ acilmente puede ocurrir que el programa genere un error de ejecuci´ on y el sistema operativo lo detenga. NULL se suele definir en estas librer´ ıas as´ ı: C´ odigo C y C++ #define NULL 0 Un apuntador nulo se utiliza para proporcionar a un programa un medio de conocer cu´ ando un apuntador contiene una direcci´ on v´ alida. Es igualmente incorrecto desreferenciar el valor NULL por las mismas razones presentadas previamente. se le suele asignar el valor NULL. y as´ ı sucesivamente. existe el riesgo de sobreescribir datos de otras variables. y. etc.h y stdlib. Se suele utilizar un test condicional para saber si un apuntador es nulo o no lo es. void func() { int x = 40. // Incorrecto *p = 25.

// Esto es v´ alido *p = 3. El resultado de estas operaciones es el desplazamiento de la direcci´ on de memoria hacia adelante (suma) o hacia atr´ as (resta) por bloques de bytes del tama˜ no del tipo de dato apuntado por el apuntador. // Declaraci´ on e inicializaci´ on del apuntador constante *p = 3. arreglos y aritm´ etica de apuntadores Los arreglos y apuntadores est´ an fuertemente relacionados. // Instrucci´ on equivalente a la anterior cout << *lista_ptr. char ***pppc = &ppc. // Esto es v´ alido 11. y = 7. Esto permite recorrer arreglos utilizando apuntadores. Ejemplos: 5 . 20. 30. Ejemplo: C´ odigo C y C++ int x = 5. Ejemplos: C´ odigo C y C++ int lista_arr[5] = {10. // Instrucci´ on equivalente a la anterior Es posible sumar y restar valores enteros a un apuntador. Se pueden direccionar arreglos como si fueran apuntadores y apuntadores como si fueran arreglos. Ejemplo: C´ odigo C y C++ char c = ’z’. // Instrucci´ on equivalente a la anterior cout << *lista_arr. y = 7. int *lista_ptr. // Instrucci´ on equivalente a la anterior cout << lista_arr[3]. const int *p = &x. lista_ptr = lista_arr. Esto hace que no sea posible modificar el valor al que apunta el apuntador. char **ppc = &pc. // Esto es v´ alido p = &y. pero s´ ı se permite la modificaci´ on del valor al que apunta.apuntadores se declaran colocando tantos asteriscos (‘*’) como sea necesario. Apuntadores. // Imprime 10 cout << lista_ptr[0]. char *pc = &c. Ejemplo: C´ odigo C y C++ int x = 5. no se permite la modificaci´ on de la direcci´ on almacenada en el apuntador. // Esto no es v´ alido (el compilador genera un error) Tambi´ en es posible declarar apuntadores a datos constantes. Apuntadores constantes y apuntadores a constantes Es posible declarar apuntadores constantes. ***pppc = ’m’. // Declaraci´ on e inicializaci´ on del apuntador a constante p = &y. // Cambia el valor de c a ’m’ 10. El nombre de un arreglo es simplemente un apuntador constante al inicio del arreglo. // A partir de aqu´ ı ambas variables apuntan al mismo sitio cout << lista_arr[0]. 40. 50}. // Esto no es v´ alido (el compilador genera un error) y = 3. De esta manera. int *const p = &x. // Imprime 40 cout << lista_ptr[3].

int *p. char *q. y luego un c´ odigo equivalente en C o C++ utilizando un apuntador: C´ odigo C++ void suma(int a. "Programando"). 2. q++) cout << q.1}. p = &lista[3]. 4. double *p = &x[1]. n = q . 20. *q = &x[4]. 30. 5. x). int& r) { r = a + b. } void main() { int x. Sin embargo. A continuaci´ on se muestra un ejemplo del paso de un par´ ametro por referencia en C++.C´ odigo C y C++ int lista[5] = {10. Instrucci´ on equivalente a la anterior // Las siguientes instrucciones imprimen la palabra "Programando" /* Nota: Recu´ erdese que una constante de cadena de caracteres es una secuencia de caracteres en memoria seguidos del c´ aracter nulo */ strcpy(cad. int b.1. Ejemplo: C´ odigo C y C++ double x[5] = {1. *q != ’\0’. cout << *(lista+2). El resultado de esta operaci´ on es el n´ umero de bloques de bytes que hay entre las dos direcciones del tama˜ no del tipo de dato apuntado por los apuntadores. cout << lista[2]. es posible hacerlo a trav´ es del uso de apuntadores. char cad[15]. Tambi´ en es posible restar dos apuntadores. suma(7. Apuntadores para paso de par´ ametros por referencia El lenguaje C no provee una manera de pasar par´ ametros por referencia. 40.1. 3. // // // // ’p’ almacena la direcci´ on de la posici´ on 3 del arreglo Instrucci´ on equivalente a la anterior Imprime 30. p = lista + 3. cout << "7 + 5 = " << x. // a ’n’ se le asigna 3 12. } 6 . 50}. 5. int n.p. for (q = cad.1.1.

En C est´ an disponibles varias funciones que permiten realizar reservar y librerar memoria. El operador ‘&’ tiene dos significados como operador unario: se˜ nalaci´ on de par´ ametro por referencia y operador de referenciaci´ on. y la funci´ on free() permite liberar la memoria reservada a trav´ es de un apuntador. Por esta raz´ on.1. } N´ otese que en ambos casos se utiliza el operador ‘&’ para cosas distintas. 5. definidas t´ ıpicamente en el archivo de cabecera stdlib. La funci´ on malloc() reserva memoria y retorna su direcci´ on. retornando un apuntador a void. tomada de la zona de memoria llamada mont´ ıculo (heap ) o almac´ en libre. pero C++ adem´ as provee un m´ etodo m´ as f´ acil y seguro de hacerlo. &x). int *r) { *r = a + b. ayud´ andose con el uso del operador sizeof.C´ odigo C y C++ void suma(int a. Ejemplos: 7 . 13. Las variables declaradas globales en sus programas se almacenan en posiciones fijas de memoria. La sintaxis de ambas funciones es como sigue: C´ odigo C y C++ void *malloc(size_t tam_bloque). y todas las funciones pueden utilizar estas variables. int b. Como se puede apreciar. malloc() reserva memoria sin importar el tipo de datos que se almacenar´ a en ella. void free(void *bloque). Tambi´ en es posible reservar y utilizar memoria din´ amicamente. Las variables locales se almacenan en la pila (stack ) y existen s´ olo mientras est´ an activas las funciones donde est´ an declaradas. Tambi´ en es necesario calcular exactamente cu´ antos bytes se requieren reservar. suma(7. // size_t es un tipo de datos entero. } void main() { int x. Asignaci´ on din´ amica de memoria al estilo de C Para asignar memoria din´ amicamente en C se utilizan las funciones malloc() y free(). o retorna NULL en caso de no haber conseguido suficiente memoria. // tam_bloque es el tama~ no en bytes // del bloque de memoria a reservar. En ambos casos el espacio de almacenamiento se reserva en el momento de la compilaci´ on del programa.h. en la zona conocida como segmento de datos del programa. se hace necesario convertir el tipo de apuntador al tipo del apuntador que guardar´ a la direcci´ on. Asignaci´ on din´ amica de memoria Los programas pueden crear variables globales o locales. 13. cout << "7 + 5 = " << x. // bloque es un apuntador a la zona // de memoria a liberar.

} Data. El operador new reserva memoria para un tipo de datos espec´ ıfico y retorna su direcci´ on. } // Verificaci´ on de reservaci´ on // Inicializaci´ on de datos // en la memoria reservada // Liberaci´ on de memoria 13. Asignaci´ on din´ amica de memoria al estilo de C++ Para asignar memoria din´ amicamente en C++ se utilizan los operadores new y delete. // Declaraci´ on de un apuntador a Data int i.2. Data *p_data. "Rachel").nombre >> p_data[i]. p_data->edad = 21. int edad. y el operador delete permite liberar la memoria reservada a trav´ es de un apuntador. // Liberaci´ on de memoria del arreglo free(p_data). De no ser as´ ı.C´ odigo C y C++ typedef struct { char nombre[20]. if (p_data != NULL) // Verificaci´ on de reservaci´ on { // Lectura de datos del arreglo for (i = 0. se produce un error de compilaci´ on. } // Reservaci´ on de memoria para un arreglo de 10 registros p_data = (Data*) malloc(sizeof(Data)*10).edad. o retorna NULL en caso de no haber conseguido suficiente memoria. i++) cin >> p_data[i]. p_data = (Data*) malloc(sizeof(Data)). La sintaxis de ambos operadores es como sigue: Para reservar y liberar un solo bloque: <apuntador> = new <tipo de dato> delete <apuntador> Para reservar y liberar varios bloques (un arreglo): <apuntador> = new <tipo de dato>[<n´ umero de bloques>] delete [] <apuntador> El tipo del apuntador especificado del lado izquierdo del operador new debe coincidir con el tipo especificado del lado derecho. i < 10. free(p_data). Ejemplos: 8 . // Reservaci´ on de memoria para un registro if (p_data != NULL) { strcpy(p_data->nombre.

delete p_data. "Rachel"). // Liberaci´ on de memoria del arreglo delete [] p_data. } // Reservaci´ on de memoria para un arreglo de 10 registros p_data = new Data[10]. p_data = new Data. if (p_data != NULL) // Verificaci´ on de reservaci´ on { // Lectura de datos del arreglo for (i = 0. }.nombre >> p_data[i]. Bibliograf´ ıa El presente art´ ıculo fue realizado con la ayuda del libro “Programaci´ on en C++ ”. // Reservaci´ on de memoria para un registro if (p_data != NULL) { strcpy(p_data->nombre. // Declaraci´ on de un apuntador a Data int i. i < 10.edad.C´ odigo C++ struct Data { char nombre[20]. int edad. i++) cin >> p_data[i]. Data *p_data. del autor Luis Joyanes Aguilar. } // Verificaci´ on de reservaci´ on // Inicializaci´ on de datos // en la memoria reservada // Liberaci´ on de memoria 14. 9 . editorial Mc Graw Hill. p_data->edad = 21.

You're Reading a Free Preview

Descarga
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->