Estructuras de Datos Punteros y algo más. Un puntero es una variable que almacena la dirección de...
-
Upload
vidal-minas -
Category
Documents
-
view
5 -
download
1
Transcript of Estructuras de Datos Punteros y algo más. Un puntero es una variable que almacena la dirección de...
Estructuras de Datos
Punteros y algo más
• Un puntero es una variable que almacena la dirección de memoria de otra variable
• Para obtener la dirección de una variable se utiliza el operador de referencia:
&nombre_variable
• Veamos un ejemplo:
int A;A=50;cout<<"La dirección de A es: "<< &A;cout<<" El valor de A es: "<<A;
• Esto imprimirá algo como:La dirección de A es: 0x0012FF7C El valor de A es: 50
• Para declarar un puntero a una variable de un tipo dado se usa la siguiente sintaxis:tipo_var *nombre_puntero;
• Ejemplo:int A=50;int *P;P=&A;
• Se declara un puntero (a entero) P, se le asigna la dirección del entero A, por tanto P queda apuntando a A
• El operador de indirección * permite acceder a la variable cuya dirección se encuentra guardada en un puntero (ya sea para acceder al valor almacenado en la variable o para modificarlo)
• El operador de indirección usa la siguiente sintaxis:*nombre_puntero
• Veamos un ejemplo:
int A=50;int *P;
P=&A;cout<< *P; // Imprime 50*P=100;cout<< *P; // Imprime 100 cout<< A; // Imprime 100
Paso de argumentos por referencia
• Con este método la función recibe las direcciones de las variables sobre las cuales se va a operar
• Por lo tanto la función puede cambiar los valores de dichas variables usando el operador *
• Veamos un ejemplo:
Sea la función sumap:
int sumap(int *a, int *b, int c) {
c = *a + *b;/*Dentro de la función, a y b son dos
variables locales de tipo puntero a int*/*a = c;*b = c;return c;
}
void main(){
int a=3;int b=2;int c=0;int r=0;r=sumap( &a, &b, c );
cout<<”Valores finales: \n“; cout<<”a=”<<a; // Imprime 5 cout<<”b=”<<b; // Imprime 5 cout<<”c=”<<c; // Imprime 0 cout<<”r=”<<r; // Imprime 5}
Aritmética de punteros
• Sobre los punteros es posible sumar y restar números enteros, estas operaciones se usan para cambiar el lugar de la memoria al que apunta el puntero
• La aritmética de punteros tiene en cuenta el tamaño de la variable apuntada.
• Las operaciones sobre punteros deben usarse con precaución, ya que al cambiar indiscriminadamente los lugares de la memoria a los que se apunta se pueden sobrescribir accidentalmente otros datos
void main(){ int a=654; int *p;
p=&a; p++; cout<< *p << "y" << *(p-1); // Imprimió: 1245120 y 654 }
Arreglos
• El identificador (o nombre) de un arreglo siempre se refiere a la dirección del primer elemento
• Para crear un puntero a un arreglo, simplemente se declara una variable puntero al tipo de los elementos del arreglo
• Este puntero puede ser acompañado de +i para acceder al elemento i del arreglo
Figura 1.4: arreglos y punteros
50 A
[0001]
50
[0003]
50
[0005]
50
[0007]
int *p1; int *p2; int *p3; p1=A; //Dir. ele 1 p2=&p1[1]; //Dir. ele 2 p3=p1+3; //Dir. ele 4
0001 p1
[0023]
0003 p2
[0345]
0007 p3
[0090]
0 1 2 3
Dirección de p1
Las siguientes expresiones son equivalentes:(p1 +3) , (A + 3) y (&p1[3])
A
p1 p2 p3
Recorrido de un vector usando punteros:
void main(){
int A[]={2, 5, 87, 21, 34}; int *p;
p=A;for(int i=0; i<5; i++){
cout<<"Elemento "<<i<<"="<<*p<<"\n";
p++;}
}
Memoria dinámica
• La memoria dinámica (heap) permite a los programas pedir y liberar espacio de memoria durante su ejecución a medida que lo necesiten
• Las variables asignadas dinámicamente, residen en el heap, no están sujetas a las reglas de duración vistas en el módulo anterior
• Útil para declarar el tamaño de arreglos en tiempo de ejecución
• La función malloc() reserva un espacio de memoria de tamaño dado en el heap y retorna un puntero a dicho espacio (si no había memoria suficiente, retorna NULL) • malloc() utiliza la siguiente sintaxis:
puntero = ( tipo_de_variable * ) malloc ( numero_de_bytes );
• Se requiere incluir stdlib.h• Veamos un ejemplo:
int *crear_arreglo(int n){
int *p;p=(int *)malloc( n*sizeof(int) );for(int i=0; i<n; i++){ p[i]=1;
}return p;
}void main(void){ int *a; a=crear_arreglo(4); free(a); //Liberar espacio reservado}
• La función free() libera un espacio de memoria reservado mediante malloc(), no retorna nada y utiliza la siguiente sintaxis:
free( direccion );
• También se puede usar en vez de malloc() la función new() así:puntero= new tipo_de_dato [n];
El mismo programa anterior hecho con new():
int *crear_arreglo_new(int n){
int *p;p= new int[n];for(int i=0; i<n; i++)
p[i]=1;return p;
}
Recursión
• Un algoritmo es recursivo si se encuentra definido en términos de sí mismo
• Es posible que una función se llame a sí misma, para ello basta con invocarse dentro de la función a ella misma y pasarle los argumentos correspondientes.
• A este tipo de función la denominamos “recursiva”
Ejemplo: El factorial de un número N sedefine como:
Si N 0 entonces: N! =N*(N-1)! Si N=0 entonces: N! =1
Veamos como programar esta función en C++ recursivamente Es natural hacerlo de manera debido a que la función se define en términos de si misma
int factorial(int n){
if(n==0) return 1;else return (n*factorial(n-1));
}
void main(){
int a;a=factorial(3);
}
Vamos a realizarle un seguimiento manualmente para ver como evoluciona esta función en el Stack…