Apuntadores Unidad 3 Primavera 2010 Dra. Ruth M. Aguilar Ponce Contenido Conceptos básicos Declaración de apuntadores Paso de apuntadores a funciones Aritmética de apuntadores Apuntadores y arreglos Apuntadores multidimensionales Apuntadores a funciones Conceptos Básicos Una variable es un objeto con nombre y valor variable. int suma = 0 nombre: suma, valor inicial: 0 Memoria Una variable es almacenada en la memoria. dirección suma Cada variable requiere de un tamaño de memoria por ejemplo: int requiere de 4 bytes char requiere de 1 byte Determine el tamaño de Variables La función sizeof(type) determina la cantidad de bytes requeridos para guardar una variable del tipo type Ejemplo: #include <stdio.h> #include <stdlib.h> int main() { printf("Tamanio de char es %d\n", sizeof(char)); printf("Tamanio de int es %d\n", sizeof(int)); printf("Tamanio de float es %d\n", sizeof(float)); system("pause"); } Declaración de variable La siguiente declaración le dice al compilador que requiere un espacio de memoria para almacenar un entero y que ese bloque estará asociado a la variable k int k; k Cuando realizamos lo siguiente el compilador introduce el valor a ese bloque de memoria k = 2; k 2 Definición Un apuntador es un variable que contiene la dirección de una bloque de memoria Un apuntador es declarado usando el operado * tipo_dato *nombre_variable Ejemplo: int *p p dirección bloque de tamaño int Operador de indirección (*) y dirección (&) El operador de dirección ( & ) nos permite tomar la dirección de la variable Ejemplo: para obtener la dirección donde se encuentra almacenada la variable k debo usar lo siguiente &k El operador de indirección (*) actúa sobre el apuntador permitiendo acceder a la variable que esta apuntando Ejemplo int *p p permite definir la dirección a la cual apunta p *p permite acceder a la variable que apunta p Operador de indirección (*) y dirección (&) main() { int k = 2; int *p; p = &k; *p = *p + 1; // p apunta a la variable k // incrementa el valor de k } p dirección de k k 2 Ejercicio Determina el valor de x, y, objeto apuntado por ip para cada linea del siguiente ejemplo int x = 1, y = 2, z[10]; int *ip; ip = &x; y = *ip; *ip = 0; ip = &z[0]; Solución Código x y ip valores iniciales ip = &x; 1 2 null 1 2 x y 1 1 x *ip = 0; 0 1 x ip 0 1 z[0] = *ip; = &z[0]; Paso de Apuntadores a una Función El uso de apuntadores nos permite pasar los parámetros por referencia o por dirección Cuando pasamos un parámetro por referencia estamos pasando la dirección donde se encuentra ese elemento. La función tiene la capacidad de acceder al bloque de memoria donde se encuentra ese elemento y por lo tanto puede modificar dicho elemento. Los cambios hechos al valor de la variable dentro de la función se verán reflejados en la variable cuando la función a terminado su ejecución Ejemplo Paso por valor void change(int x, int y) { int temp; temp = x; x = y; y = temp; } La función no causa el efecto deseado ya que los valores solo se intercambian dentro de la función Paso por Referencia usando apuntadores void swap(int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp; } Ahora la función realmente esta intercambiando los valores Este intercambio se vera reflejado al terminar la ejecución de la función main Ejemplo u #include <stdio.h> #include <stdlib.h> v void change(int x, int y); void swap(int *x, int *y); main() { int u = 5, v = 10; printf("Antes de change u change(u,v); printf("Despues de change printf("Antes de swap u = swap(&u,&v); printf("Despues de swap u system("pause"); return 0; } swap = %d, v = %d\n",u,v); x u = %d, v = %d\n",u,v); %d, v = %d\n",u,v); = %d, v = %d\n",u,v); y Ejemplo 2 Realiza un programa que lea una frase y la analice para encontrar los siguientes datos: Numero de vocales Numero de consonantes Numero de dígitos Numero de blancos Numero de cualquier otro carácter que no pertenezca a las clases antes mencionadas Solución void ScanLine(char phrase[], int *v, int *co, int *d, int *b, int *o) { int i=0; char c; *v = 0; *co = 0; *d = 0; *b = 0; *o = 0; while((c=toupper(phrase[i]))!= '\0') { if(c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') ++ *v; else if( c >= 'A' && c <= 'Z') ++ *co; else if( c >= '0' && c <= '9') ++ *d; else if (c == ' ' || c == '\t') ++ *b; else ++ *o; i++; } } Solución #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX 100 void ScanLine(char phrase[], int *v, int *co, int *d, int *b, int *o); main() { char frase[MAX]; int voc,con,dig,blancos,otros; printf("Proporciona una frase "); gets(frase); ScanLine(frase,&voc,&con,&dig,&blancos,&otros); printf("La frase contiene %d vocales\n",voc); printf("La frase contiene %d consonantes\n",con); printf("La frase contiene %d digitos\n",dig); printf("La frase contiene %d blancos\n",blancos); printf("La frase contiene %d caracteres diversos\n",otros); system("pause"); return 0; } Uso indebido de apuntadores #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX 100 void ScanLine(char phrase[], int *v, int *co, int *d, int *b, int *o); main() { char frase[MAX]; int *voc,*con,*dig,*blancos,*otros; printf("Proporciona una frase "); gets(frase); ScanLine(frase,voc,con,dig,blancos,otros); printf("La frase contiene %d vocales\n",voc); printf("La frase contiene %d consonantes\n",con); printf("La frase contiene %d digitos\n",dig); printf("La frase contiene %d blancos\n",blancos); printf("La frase contiene %d caracteres diversos\n",otros); system("pause"); return 0; } Apuntadores y Arreglos Los apuntadores están fuertemente relacionados a los arreglos Cualquier operación que pueda ser relacionada con arreglos también puede realizarse con apuntadores Una variable de tipo arreglo es realmente un apuntador al primer elemento del arreglo int x[10] x x[0] x[3] x x+3 x+9 Operaciones con Apuntadores Si tenemos un apuntador *pa y este apunta al primer elemento del arreglo a[0], entonces pa+1 apunta al siguiente elemento y pa+i apunta al i-esimo elemento El concepto de agregar uno al apuntador nos indica que el apuntador se movera al siguiente elemento del arreglo sin importar el tipo del arreglo Esta es la razón por la cual es importante declarar el tipo de apuntador, basados en el tipo, el apuntador se movera el número de bytes correspondiente a la siguiente variable Ejemplo int *p entonces p+1 se moverá 4 bytes char *p entonces p+1 se moverá 1 byte double *p entonces p+1 se moverá 8 bytes Apuntadores y Arreglos int A[10]; int *pa; Debido a que A es un apuntador a la primera posicion del arreglo, podemos escribir pa = &A[0]; pa = A Para obtener el elemento del arreglo en la posición i entonces escribimos pa *(pa+i) x x[0] x[3] pa pa+3 pa+9 Ejemplo 3 #include <stdio.h> #include <stdlib.h> int cadlong(char *s); main() { char C[100]; printf("Proporciona una frase "); gets(C); printf("La longitud de tu frase es %d\n\n",cadlong(C)); system("pause"); return 0; } int cadlong(char *s) { int n; for(n=0; *s != '\0'; s++) n++; return n; } Ejemplo 4 #include <stdio.h> #include <stdlib.h> void strcpy1(char *s, char *t); main() { char C1[100],C2[100]; printf("Proporciona una frase "); gets(C1); strcpy1(C2,C1);printf("La frase leida fue %s\n\n",C2); system("pause");return 0; } void strcpy1(char *s, char *t) { int i = 0; while(t[i] != '\0') { s[i]=t[i]; i++; } s[i] = '\0'; } Versión 2 void strcpy2(char *s, char *t) { while(*t != '\0') { *s = *t; s++; t++; } *s = '\0'; } Versión 3 void strcpy3(char *s, char *t) { while((*s = *t) != '\0') { s++; t++; } } Versión 4 void strcpy4(char *s, char *t) { while((*s++ = *t++) != '\0'); } void strcpy5(char *s, char *t) { while((*s++ = *t++)); }