Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación UNIDAD 6: APUNTADORES O PUNTEROS CONTENIDOS 6.1. Introducción a los apuntadores o punteros 6.1.1. Parámetros de dirección Parámetros de referencia 6.1.2. Apuntadores o punteros Diferencias entre una referencia y un apuntador 6.1.3. Despliegue y almacenaje de domicilios 6.2. Declaración de apuntadores o punteros 6.3. Ejemplos de apuntadores o punteros en C++ OBJETIVOS DE LA UNIDAD Conocer el concepto básico de puntero y aplicarlo al desarrollo de programas. Desarrollar habilidades en el uso de punteros para la construcción de aplicaciones básicas con DevC++. 6.1. Introducción a los apuntadores o punteros 6.1.1. Parámetros de dirección C++ permite dos tipos de parámetros de dirección: - Referencias - Apuntadores o punteros Parámetro de referencia Se utiliza para transmitir la dirección de una variable a una función llamada. Para desplegar el domicilio de una variable en C++ puede emplearse el operador de domicilio o de dirección, & (se lee “el domicilio de”). En C++ un parámetro de referencia se declara utilizando la siguiente sintaxis: Tipo-de-datos& nombre-de-referencia Por Ejemplo: flota& num1; Declara que num1 es un parámetro de referencia que se utilizará para almacenar la dirección de un float. Ejemplo: Elevar al cubo una variable mediante una llamada por referencia. #include<iostream> #include<conio.h> using namespace std; //Prototipo de la funcion void cuboPorReferencia(int *); int main() { int numero=5; cout <<"El valor original de numero es: " <<numero <<endl; //Llamada a la funcion …/ 73 ... Apuntadores o Punteros Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación cuboPorReferencia(&numero); cout <<"El nuevo valor de numero es: " <<numero; getch(); return 0; } //Definicion de la funcion void cuboPorReferencia(int *ptrN) { *ptrN=*ptrN * *ptrN * *ptrN; } 6.1.2. Apuntadores o punteros Son variables que se emplean para almacenar domicilios en memoria (o domicilio de otras variables). Dicho de otra manera, un puntero es un tipo especial de variable, que almacena el valor de una dirección de memoria, esta dirección puede ser la de una variable individual, pero más frecuentemente será la de un elemento de un arreglo (array), una estructura (struct) u objeto de una clase. Para entender mejor el concepto de puntero, es necesario partir de los parámetros de dirección permitidos en C++. Independientemente del tamaño (sizeof) del objeto apuntado, el valor almacenado por el puntero será el de una única dirección de memoria. En sentido estricto un puntero no puede almacenar la dirección de memoria de 'un array' (completo), sino la de un elemento de un array, y por este motivo no existen diferencias sintácticas entre punteros a elementos individuales y punteros a arrays. La declaración de un puntero a char y otro a array de char es igual. Diferencias entre una referencia y un apuntador Referencias Apuntadores - El domicilio denominado como referencia no puede alterarse. - Las referencias se desreferencian automáticamente. - Uso del operador de domicilio, &. - El domicilio en el apuntador puede cambiar. Los apuntadores se deben desreferenciar explícitamente para localizar el valor al que accedan. - Uso del operando de indirección, *. 6.1.3. Despliegue y almacenaje de domicilios - Desplegar el domicilio de una variable. Ejm: cout <<&num1; Almacenar los domicilios de las variables declaradas. Ejm: d = &m; // d almacena el domicilio de variable m. Empleo de domicilios Para emplear un domicilio almacenado, C++ dispone de un operador de indirección, *. Por ejemplo, *d se puede leer como:”la variable que apunta a d” Una variable apuntador ‘y’ mmmm El contenido del domicilio mmmm es qqqq qqq q …/ 74 ... El contenido de ‘y’ es un domicilio mmmm Apuntadores o Punteros Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación Cuando se emplea una variable apuntador, el valor final siempre se encuentra al ir primero por un domicilio a la variable apuntador. La dirección contenida en el apuntador se emplea para obtener el contenido deseado. 6.2. Declaración de apuntadores o punteros Los apuntadores deben declararse antes de emplearse para almacenar un domicilio, considerando: - Tipo de variable a la cual apunta - Operador de indirección *. - Nombre de la variable (no usar constantes). Por ejemplo: int *direnum; se lee: “la variable que apunta a dirnum es un numero entero”. float *apunta_tam; Se lee: “la variable a la que apunta apunta_tab es un float”. Desreferenciacion ("indirection") Un puntero almacena una dirección de memoria de alguna entidad, esto en si mismo no seria demasiado útil si no fuera posible, a través del puntero, acceder a lo que esta almacenado en esa dirección. Según el creador de C++: "la operación fundamental de un puntero es desreferenciar, es decir, referir al objeto al que apunta el puntero" (Stroustrup, 1997). La función de 'desreferenciar' un puntero es llevada a cabo por el operador '*', que además cumple otras funciones en C++. Como su papel es complementario a una de las funciones del operador '&' se comenzará estudiando la relación y diferencia de estos dos operadores. Ambos operadores tienen más de un sentido dependiendo del contexto en que aparecen, por lo tanto son casos de sobrecarga de operadores. Veamos sus distintos usos: OPERADOR Usos * Multiplicación int a = 3, b=2, c; c = a * b; Declaración tipo puntero int n; int* p = n; Dereferencing (indirection) cout<<*p; & Operacion Bitwise AND char a=0x37; a &=0x0F; Declaración del tipo referencia int a; int &b = a; Referencing cout<<&a; El primer uso de cada operador se distingue claramente de los otros dos, derivan de C y no tienen relación con el tema punteros. Los que figuran en segundo lugar pertenecen a la sintaxis básica de declaración de punteros y referencias. Nos concentraremos en el tercer significado de estos operadores. …/ 75 ... Apuntadores o Punteros Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación El papel opuesto y complementario del tercer uso de ambos operadores se podría sintetizar así: dadas las siguientes declaraciones: int v = 4; int* p = &v; El puntero 'p' es equivalente a la dirección de memoria a la que apunta. La variable 'v' es equivalente al valor que almacena cout<<p saca en pantalla una dirección de memoria (por ej: 0x8f70fff0) cout<<v saca en pantalla '4' Mientras que la expresión '&v' es un sinónimo de Mientras que la expresión '*p' es sinónimo del la dirección de memoria donde se encuentra esa elemento individual que se encuentra en la localidad variable apuntada por el puntero cout<<&v saca en pantalla una dirección de memoria (ej: 0x8f70fff0) cout<<*p saca en pantalla '4' Como puede observarse, el efecto de ambos operadores es inverso, en un caso dada una localidad de memoria se accede al elemento almacenado en ella (el caso de '*'), en el otro ('&') dada una variable accedemos a la dirección de memoria donde almacena su valor. El termino usado para este efecto del operador '*' es el de 'indirection' o 'dereferencing' traducido generalmente como 'indirección' o 'desreferenciación'. Su sentido más llano seria: operador que permite referirnos al elemento individual apuntado por el puntero, en lugar de la dirección en que ese elemento se encuentra almacenado. 6.3. Ejemplos de apuntadores o punteros en C++ 1. Programa que convierte una cadena de caracteres de minúsculas a mayúsculas mediante un apuntador no constante a un dato no constante. #include<iostream> #include<conio.h> #include<ctype.h> using namespace std; //Prototipo de la funcion void convierteAMayusculas(char *); int main() { char cadena[]="Caracteres y $32.98"; cout <<"\nLa cadena antes de la conversion es: " <<cadena; //Llamada a la funcion convierteAMayusculas(cadena); cout <<"\nLa cadena despues de la conversion es: " <<cadena; getch(); return 0; } //Definicion de la funcion void convierteAMayusculas(char *ptrS) { while (*ptrS != '\0') { if (islower(*ptrS)) …/ 76 ... Apuntadores o Punteros Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación { *ptrS=toupper(*ptrS); } ++ ptrS; } } NOTA: − La función islower de la biblioteca estándar convierte un carácter a su letra correspondiente en minúscula. − La función toupper de la biblioteca estándar convierte un carácter a su letra correspondiente en mayúscula. 2. El siguiente programa imprime una cadena carácter por carácter mediante un apuntador no constante a un dato constante. #include<iostream> #include<conio.h> using namespace std; //Prototipo de la funcion void imprimirCaracteres(const char *ptrS); int main() { char cadena[]="Imprimir los caracteres de una cadena"; cout <<"\nLa cadena es: "; //Llamada a la funcion imprimirCaracteres(cadena); cout <<"\n"; getch(); return 0; } //Definicion de la funcion void imprimirCaracteres(const char *ptrS) { for ( ; *ptrS != '\0';ptrS++) //For sin inicializacion { cout <<*ptrS; } } 3. Declaración de un puntero a int y de la utilización de los operadores de referencia (&) y desreferencia (*). #include <iostream> #include <conio.h> using namespace std; int main() { // DECLARACION DE UN PUNTERO A ENTERO int* puntero_a_entero=NULL; int a=0; puntero_a_entero = &a; // El puntero se inicializa con la direccion de memoria de a; a=8; cout << " &a =" << &a << endl; cout << " a = " << a; …/ 77 ... Apuntadores o Punteros Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación cout << "\n puntero_a_entero = " << puntero_a_entero << endl << endl; cout << "\n *puntero_a_entero = " << *puntero_a_entero; getch(); return 0; } 4. Declaración de un puntero a int y de la utilización de los operadores de referencia (&) y desreferencia (*) utilizando funciones. # include <iostream> #include<conio.h> using namespace std; void func(int *); // prototipo: argumento definido como puntero-a-int main () { int x = 35; int * ptr = &x; cout<<x <<endl; cout<<ptr <<endl; cout<<*ptr <<endl; func (ptr); // se pasa puntero-a-int como argumento cout << "El valor es ahora: " << x << endl; getch(); return (0); } void func (int * p) { // el argumento se define como puntero-a-int *p =*p +10; // el argumento es tratado como puntero } …/ 78 ... Apuntadores o Punteros Universidad Don Bosco (UDB) Facultad de Ingeniería / Escuela de Computación “Apuntadores o punteros” Tercera Edición revisada. Septiembre de 2007. Elaborado y Presentado por Milton José Narváez Sandino, Ingeniero en Computación y Sistemas, para la asignatura Programación I. Universidad Don Bosco (UDB) – Facultad de Ingeniería – Escuela de Computación. FUENTES DE CONSULTA BIBLIOGRAFIA DALE, Nell / WEEMS, Chip. PROGRAMACIÓN Y RESOLUCIÓN DE PROBLEMAS CON C++. Cuarta edición. Editorial McGraw Hill, México, 2007. BRONSON, Gary J. C++ PARA INGENIERIA Y CIENCIAS. Segunda edición. Editorial International Thomson, México 2007. CAIRO, Osvaldo. METODOLOGIA DE LA PROGRAMACION. Segunda edición. Editorial Alfaomega, México 2003. DEITEL, Harvey M. / DEITEL, Paul J. CÓMO PROGRAMAR EN C++ Y JAVA. Cuarta Edición. Editorial Pearson Prentice Hall, México, 2004. JOYANES Aguilar, Luís. PROGRAMACIÓN EN C++ - ALGORITMOS, ESTRUCTURAS DE DATOS Y OBJETOS. Editorial McGraw Hill, España, 2000. SITIOS WEB http://www.romalo.250x.com/contenido/ci/index15.htm http://www.infonet.com.ve/informaciongeneral/tecnologiagsm/default.aspx http://microasist.com.mx/noticias/internet/fimin271003.shtml http://www.ericsson.com.mx/press/referencias/tec_gsm.html …/ 79 ... Apuntadores o Punteros