330 likes | 511 Views
Diseño de algoritmos “Punteros”. Claudio Gutiérrez-Soto. Punteros. Un puntero es una variable que hace referencia a una dirección de memoria Sintaxis: Tipo_Dato *nombre_variable_puntero; Ejemplo: int *p; Asignación de Dirección nombre_puntero=&variable;. Punteros.
E N D
Diseño de algoritmos“Punteros” Claudio Gutiérrez-Soto.
Punteros Un puntero es una variable que hace referencia a una dirección de memoria Sintaxis: Tipo_Dato *nombre_variable_puntero; Ejemplo: int *p; Asignación de Dirección nombre_puntero=&variable;
Punteros El carácter & delante de una variable indica que lo se está accediendo es a la dirección de memoria de dicha variable. Ejemplo: int *p; p=0; /* p posee la dirección NULL ó 0*/ p=NULL; /* p posee la dirección NULL ó 0*/ p=&i; /*p apunta hacia i ó conteniendo la dirección de i */ p=(int )1501; /*dirección absoluta de memoria */
Punteros " Si p es un puntero, entonces *p es el valor de la variable a la que apunta .“ Ejemplo: double x,y,*p; p=&x; y=*p; Lo anterior es equivalente a : y=*&x; y=x;
Punteros Inicialización Sintaxis: tipo_dato *nombre_puntero=&variable; Ejemplo: int i=7,*p=&i;
Punteros Construcciones a las que no se debe apuntar. *No apuntar a constantes. &3 /* ilicito*/ *No apuntar a arreglos, el nombre de un arreglo es una constante int a[77]; &a; *No apuntar a expresiones ordinarias &(k+99)
Punteros *No apuntar a variables de tipo register. register v; &v; *Si a es un arreglo, expresiones como: &a[0] y a[i+j+3] adquieren sentido
Punteros int i=3, j=5, k,*p=&i, q=&5,r; double x=11.5;
Punteros Llamada por valor Máx(a,b) Int a,b; { return((a>b)?a:b); } Llamado por referencia Máx(a,b,m_ptr) Int a, b,*m_ptr; { *m_ptr=(a>b)?a:b; }
Punteros Relación entre punteros y arreglos. Un puntero es una variable cuyos valores son direcciones. El nombre de un arreglo es una dirección o puntero fijo. Cuando se declara un arreglo, el compilador debe asignar una dirección base y la cantidad de almacenamiento suficiente como para alojar a todos los elementos del arreglo.
Punteros #define TAM 100 int a[TAM], *p; y el sistema hece que los bytes numerados 300, 304, 309,......696 sean las direcciones de a[0], a[1], a[2],...,a[99]. p=a; = p=&a[0];
Punteros Aritmética de punteros La aritmética de puntero proporciona una opción para la indización de arreglos, las proposiciones p=a+1; = p=&a[1]; Sumar un arreglo: suma=0; for(p=a; p<&a[TAM];++p) suma+=*p;
Punteros suma=0; for(i=0;i<TAM;++i) suma+=*(a+i); Debido a que a es un puntero constante, las expresiones como: a=p; ++a; a+=2; Son ilícitas, no se puede cambiar la dirección de a. Expresiones apuntadoras como p+1, ++p y p+=i son válidas. Double a[ ]; = double*a;
Punteros Cadenas Las cadenas son arreglos unidimensionales de tipo char, Por convención, una cadena en C se termina con centinela de fin de cadena ó carácter nulo \0. char s[ ]="ABC" char *p="a es por anon o pastel alfabeto" void main() { char *q="del cual todos tienen parte"; printf("\n%s,%s\n %s",s,p,q); ABC: a es por anon o pastel alfabeto del cual todos tienen parte. For(p=q;*q!='\0';++q) *q+=1 printf("\n %s\n\n",p); }
Punteros Arreglos multidimensionales Expresiones equivalentes ab[i][i] *(b[i]+j) (*(b+i))[j] *((*(b+i))+J) (&b[0][0]+5i+j) Al definir la función, en el encabezamiento, la declaración: Int (*v)[5]; = int v[ ][5]; Int c[7][9][2]; C[i][j][k] = (&c[0][0][0]+9*2+i+2*j+k)
Asignación dinámica de memoria • Cuando definimos un arreglo con un tamaño definido, podemos tener dos posibles casos, uno es un desaprovechamiento de la memoria y otro es la falta de espacio, lo cual en general no sucede.
Asignación dinámica de memoria • Por ende, podría ser posible definir: int *x; En lugar de int x[10]; • No obstante, si no conocemos el tamaño de manera predeterminada, es posible asignar espacio de manera dinámica.
Asignación dinámica de memoria • Así para asignar memoria de manera dinámica podemos utilizar la función malloc, como sigue: • x= (int *)malloc(10*sizeof(int)); • Esta función reserva un bloque de memoria cuyo tamaño (en bytes) es equivalente a 10 cantidades enteras.
Asignación dinámica de memoria • En general el <<cast>> de tipo que procede a malloc debe ser consistente con el tipo de datos de la variable puntero. • Así si quisiéramos pedir en tiempo de ejecución para una variable tipo double sería: • y=(double *)malloc(10*sizeof(double));
Asignación dinámica de memoria int i,n,*x; …. printf(“Cuántos números serán ingresados\”); scanf(“%d”,&n); /* reserva de memoria para n */ x=(int *)malloc(n*sizeof(int)); for(i=0;i<n;i++){ printf( “i=%d x=“, i+1); scanf(“%d”,x+i); }
Uso de typedef en estructuras • Recordemos que la palabra reservada typedef nos permite redefinir un tipo de dato, por ejemplo: • typedef int entero; • Es posible definir tipos de datos con la nueva definición • entero a,b,c;
Uso de typedef en estructuras • Por ello, en términos generales se puede definir. typedef struct{ miembro 1; miembro 2; miembro 3; …. }nuevo-tipo;
Uso de typedef en estructuras typedef struct{ int mes; int dia; int anho; }fecha; fecha Aux;
Estructuras y punteros • Podemos acceder a la dirección de una variable estructura de la misma manera que cualquier otra dirección, mediante el uso del operador (&). Así podemos escribir: • tipo *ptvar;
Estructuras y punteros • Ejemplo: typedef struct{ int no_cuenta; char tipo_cuenta; char nombre[80]; float saldo; }cuenta; cuenta cliente, *pc;
Estructuras y punteros • En este ejemplo cliente es una variable estructura de tipo cuenta y pc un puntero que apunta a una variable de tipo cuenta. • Por ende pc=&cliente; Así podemos acceder a un miembro individual de una estructura en términos de su correspondiente variable puntero escribiendo Ptvar->miembro Lo que es equivalente a escribir variable.miembro
Estructuras y punteros • El operador -> puede combinarse con el operador punto para acceder a un submiembro dentro de una estructura. Por lo tanto, un submiembro puede ser accedido escribiendo • ptvar->miembro.submiembro
Estructuras y punteros struct Cuenta{ int no_cuenta; char tipo_cuenta; char nombre[80]; float saldo; fecha ultimopago; }cliente,*pc=&cliente; cliente.no_cuenta, pc->no_cuenta, (*pc).no_cuenta typedef struct{ int mes; int dia; int anio; }fecha;
Estructuras y punteros struct Cuenta{ int no_cuenta; char tipo_cuenta; char nombre[80]; float saldo; fecha ultimopago; }cliente,*pc=&cliente; cliente.ultimopago.mes, pc->ultimopago.mes, (*pc).ultimopago.mes typedef struct{ int mes; int dia; int anio; }fecha;
Estructuras y punteros struct Cuenta{ int no_cuenta; char tipo_cuenta; char nombre[80]; float saldo; fecha ultimopago; }cliente,*pc=&cliente; typedef struct{ int mes; int dia; int anio; }fecha; Para acceder al tercer carácter del nombre, este puede ser accedido de la siguiente manera: cliente.nombre[2] pc->nombre[2] (*pc).nombre[2]
Ejemplo main(){ int n=3333; char t=‘A’; float b=99.99; typedef struct{ int mes; int dia; int anio; }fecha; struct Cuenta{ int *no_cuenta; char *tipo_cuenta; char *nombre; float *saldo; fecha ultimopago; }cliente,*pc=&cliente; cliente.no_cuenta=&n; cliente.tipo_cuenta=&t; cliente.nombre=“Lázaro”; cliente.saldo=&b; printf(“%d %c %s %.2f”,*cliente.no_cuenta,*cliente.tipo_cuenta, cliente.nombre,*cliente.saldo); printf(“%d %c %s %.2f \n”,*pc->no_cuenta,*pc->tipo_cuenta, pc->nombre,*pc->saldo); } 3333 A Lázaro 99.99 3333 A Lázaro 99.99