presentación de powerpoint - unpa suneoblopez/programacionestructurada...2 punteros m. c. bertha...
Post on 10-Jun-2020
12 Views
Preview:
TRANSCRIPT
1
M. C. Bertha López Azamar
Universidad del Papaloapan
Tema:
Expositor:
M. C. Bertha López AzamarTuxtepec, Oaxaca.
Enero/2005-2006
Programación Estructurada
Materia:
Punteros
2
M. C. Bertha López AzamarPUNTEROS
Un tema muy ligado al uso de arreglos y paso de parámetros por referencia a funciones, es el uso de punteros.
Un puntero, es una variable que contiene la dirección de memoria, de un dato o de otra variable que contiene al dato. (El puntero apunta al espacio físico donde está el dato de la variable).
10003
El contenido es una dirección de memoria
Puntero
3
M. C. Bertha López Azamar
memoria
Espacio de almacenamiento
Antes de continuar es importante recordar aspectos como los siguientes:
Toda variable tiene:• nombre (identificador), • tipo de dato, que permite reservar un espacio de
almacenamiento (dirección de memoria) y • contenido .
3dato
4
M. C. Bertha López Azamar
El programador al realizar la declaración de la variable, reserva un espacio de almacenamiento en memoria, conoce el nombre, pero el Sistema Operativo (S.O.) es quien asigna la dirección de memoria.
Ejemplo:
El S.O. encuentra una espacio libre de memoria y la asocia con el nombre de la variable.
int Edad; //declaración de la variable
Edad = 28; //asignación del valor
valor
Tipo de dato
Reserva 16 bits de memoria
nombrePermite referenciar ese espacio de memoria en el código
Edad
1000 Dirección de memoria de la variable
3contenido
nombre
5
M. C. Bertha López Azamar
Un puntero puede apuntar a un objeto de cualquier tipo, incluyendo variables simples, arreglos, estructuras, funciones, etc.
3
‘C’
Puntero *p Puntero
*q
50001000
Por esa razón su contenido es una dirección de memoria y no un valor cualquiera.
6
M. C. Bertha López Azamar
3
‘C’
*p
*q
5000
1000
Las variables tienen nombre, contenido y dirección de memoria.
edad
letra
1000
5000
200
300
7
M. C. Bertha López Azamar
Al hablar de puntero, se distinguen dos operadores:
- operador dirección de: & el cual devuelve como resultado la dirección de su operando.
- operador de indirección: *toma el contenido de su operando como una dirección y nos da como resultado el contenido en esa dirección.
8
M. C. Bertha López Azamar
,Menor= += -= *= /= etc.?:||&&|^&== !=< <= > =><< >>+ -* / %! ~ ++ -- - (tipo) * & sizeof ( ) [ ] -> .Mayor
Los operadores unarios * y & tienen mayor precedencia que los operadores aritméticos +, –, *, /,% e igual precendencia que ++ y --.
NOTA:
9
M. C. Bertha López Azamar
La declaración de un puntero tiene la siguiente sintaxis:
Un puntero se declara precediendo el identificador que referencia al puntero, por el operador de indirección ( * ), el cual significa “puntero a”.
tipo *var_puntero;donde:
tipo.- especifica el tipo de objeto apuntador, puede ser cualquier tipo, incluyendo tipos agregados.
var_puntero.- nombre de la variable.
Declaración de un puntero:
10
M. C. Bertha López AzamarEjemplo: se declaran dos variables simples:
*p
200
*q
300
letra
50001000
edad
Al declarar los punteros para que apunten a estas variables, estos deben ser del mismo tipo de dato que la variable a la que apuntarán.
int *p; /*declara p como puntero a un entero*/char *q; /*declara p como puntero a una cadena
de caracteres*/
int edad;char letra;
11
M. C. Bertha López Azamar
//asigna la dirección de memoria de la variable al punterop = &edad;q = &letra ;
Para asignar contenido a un PUNTERO, podemos emplear el operador de asignación (=) en conjunto con el operador de dirección (&). Pero NUNCA lea el contenido de una variable puntero con una función de lectura por teclado (por ejemplo: scanf)
3 ‘C’*p *q
50001000
Para asignar valores a variables simples, podemos emplear el operador de asignación (=) o la lectura del valor mediante una función de lectura por teclado (por ejemplo: scanf)
edad letra
1000 5000200 300
//asigna un valor a la variableedad = 3;letra = ‘C’;
3 Cletra
1000 5000
edad
12
M. C. Bertha López AzamarReuniendo el código tenemos:int edad, *p;char letra, *q;
//Las asignaciones siguientes son correctasedad = 3;letra = ‘C’;p = &edad; /*al puntero ‘p’ le asigna la dirección de memoria
de la variable edad. La cual es conocida por el sistema operativo.*/
q = &letra;//Las asignaciones siguientes son incorrectas:p = 5; /*no puedo asignarle un valor cualquiera a un puntero,
solo direcciones de otra variable del mismo tipo*/p = &letra; /*no puedo asignarle la dirección de una
variable de otro tipo de dato distinto al cual se declaro el puntero.*/
13
M. C. Bertha López Azamar
Para obtener el valor del dato al cual apunta el puntero, se emplea el operador de indirección (*) junto al nombre del puntero. Si solo se pone el nombre del puntero, lo que se obtiene es el contenido de la variable puntero, es decir, una dirección de memoria.
3
*p
1000edad
1000200*p se puede leer como sigue:
toma el contenido del puntero ‘p’ (dirección 1000), y dame el contenido que se encuentra en esa
dirección de memoria (3). dame el contenido que se encuentra en la dirección
de memoria que contiene la variable p. dame el contenido de la dirección de memoria a la
que apunta p.
14
M. C. Bertha López AzamarPor lo tanto, para obtener el contenido de la variable ‘edad’, es decir el 3, usando el puntero, debe escribirse *p, con lo que podemos accesar indirectamente al contenido que apunta el puntero ‘p’.
Al escribir el código:
edad = *p + 1;Toma indirectamente el contenido de la dirección de memoria a la que apunta ‘p’, es decir, el contenido de la variable ‘edad’ y le suma un uno y luego lo asigna a la variable edad (lo que hace es 3+1 4) . Es lo mismo que escribir: edad = edad + 1; si las variables ‘p’ y ‘edad’ se declararón en la misma función.
3
*p
1000edad
1000
200
4*p
1000edad
1000200
15
M. C. Bertha López Azamar
*p = 1; Lo que hace es asignar indirectamente un 1 al contenido de la dirección de memoria a la que apunta ‘p’, es decir, a la variable ‘edad’.
El código:
1*p
1000edad
1000200
Si lo que se quiere es leer el valor de una variable mediante un puntero, se debe recordar que al usar la variable scanf, el segundo argumento que requiere es una dirección de memoria de una variable, y que el puntero en si, ya contiene una dirección de memoria de una variable.
16
M. C. Bertha López Azamar
scanf(“%d”, &edad);
El ampersand(&), permite obtener la dirección de memoria de la variable edad. Al no ser puntero, el colocar el ampersand esto es correcto.
scanf(“%d”, p);
En el caso de leer indirectamente mediante el puntero, el uso del ampersand es incorrecto, ya que el contenido del puntero en si es la dirección de memoria donde se ubica la variable edad. Al ser puntero, el colocar el ampersand esto sería incorrecto.
Así el código:
17
M. C. Bertha López Azamar
• Crear y manipular estructuras de datos,
• Asignar memoria dinámicamente, y
• Proveer el paso de parámetros por referencia en las llamadas a funciones.
Los punteros se pueden utilizar para:
18
M. C. Bertha López Azamar
Recordemos el ámbito de las variables:• locales• globales
Función2Función1 Pasode
parámetros
datos datos
datosdatos
Variables globales
Variableslocales
Variableslocales
Respecto al paso de parámetros:
19
M. C. Bertha López Azamar
Respecto al paso de parámetros:
Básicamente puede realizarse el paso de parámetros de dos formas :
• Por valor
• Por referencia
20
M. C. Bertha López Azamar
{ A=5; B=7; Funcion( A, 18, B*3+4)}
void Funcion(int x, int y, int z){
}
5 18 25
Argumentos(parámetros actuales – pueden ser variables,
constantes, o expresiones)
parámetros formales
Copias de valores
El paso por valor, copia el valor de un argumento en el parámetro formal de la subrutina. Los cambios realizados sobre el parámetro no afectan al argumento.
5 18 25
21
M. C. Bertha López AzamarLa llamada por referencia, copia la dirección del argumento en el parámetro. Dentro de la subrutina se usa la dirección para acceder realmente al argumento usado en la llamada, con lo que los cambios sufridos por el parámetro se reflejan en el argumento.
{ A=5;B=7;Funcion( &A, &B);
}
void Funcion(int *x, int *y){
}
argumentos(parámetros actuales
– deben ser variables)
parámetros formales(variables de tipo
puntero)
direcciones de memoria
22
M. C. Bertha López Azamar#include<stdio.h>#include<conio.h>void Funcion(int *, int *);void main(){
int A =5, B=7; //muestra el contenido de A, y B, o sea 5 y 7
printf(“A = %d, B = %d”, A, B);printf(“Introduce el valor de A: ”); scanf(“%d”, &A); //lee un valor y lo guarda en AFuncion( &A, &B);
//muestra el contenido de A, y B al regresar de la funciónprintf(“A = %d, B = %d”, A, B);getch();
}
23
M. C. Bertha López Azamar
void Funcion(int *x, int *y){ /*asigna un valor en la dirección a la que apunta ‘y’, es decir, en el contenido de la variable A.*/
*x = 20; //muestra el contenido de A, y B, o sea 20 y 7
printf(“A = %d, B = %d”, *x, *y); //lee el valor de ‘B’ através del puntero ‘y’
scanf(“%d”, y); //muestra el contenido de A, y B,
printf(“A = %d, B = %d”, *x, *y;);}
24
M. C. Bertha López Azamar
Tratándose de arreglos, debe recordarse que en si el nombre del arreglo es en sí un puntero.
Al declarar un puntero lo que se hace es reservar un espacio de memoria (según el tipo de dato especificado) para un número determinado de datos y adicionalmente se reserva espacio para una variable puntero, la cual es la que tiene el nombre.
Entonces el puntero apunta al inicio del espacio de memoria reservado (la primera posición del arreglo) y permite referenciar las posiciones de memoria con ese nombre y un índice que indica en si la posición, (y el S.O. calculara con esto el desplazamiento en memoria.
PUNTEROS y ARREGLOS
25
M. C. Bertha López Azamar
Así tenemos el código de declaración de un arreglo:
int mes_d[31];
5000mes_d
4000
5000
Gráficamente podemos representarlo de la siguiente forma:
26
M. C. Bertha López AzamarEn el caso del paso de parámetros de un arreglo, siempre se realiza por referencia, tenemos que pasar una dirección de memoria, entonces solo colocaríamos el nombre del arreglo en la llamada a la función, y el prototipo y la definición de la función deben tener un puntero que reciba la dirección.Ejemplo: void lee_ahorro(float *);
void main(){
float mes[31];lee_ahorro(mes);
}void lee_ahorro(float *m){}
27
M. C. Bertha López AzamarEn C existe una relación tal entre punteros y arreglos, que cualquier operación que se pueda realizar mediante la indexación de un array, se puede realizar también con punteros.
La diferencia radica en la expresión para acceder a los elementos del arreglo:
lista[ind] ó *(lista + ind)
lo que es:
arreglo[indice] ó *(arreglo + indice)
En el arreglo del ejemplo sería:
mes[i] ó *(mes + i)
28
M. C. Bertha López AzamarDentro de la función el código que haga referencia al arreglo se maneja igual, mediante un índice se referencia la posición. (en el scanf se coloca el ampersan como siempre, ya que debe localizar la dirección de la referencia)
Ejemplo: void lee_ahorro(float *);void main(){
float mes[31];lee_ahorro(mes);
}void lee_ahorro(float *m){
m[2] = 10; scanf("%d", &m[2]);}
29
M. C. Bertha López Azamar
En el caso de las cadenas de caracteres, se manejan indiferentemente como arrays, y se puede aplicar lo expuesto para los arrays. Particularmente, puede mencionarse que para hacer referencia a una cadena de caracteres, podemos utilizar un puntero o un array:
/*utilizando un puntero*/char *nombre = “Benito Juárez”;
/*utilizando un arreglo*/char nombre[ ] = “Benito Juárez”;
30
M. C. Bertha López Azamar
ARRAYS DINÁMICOS
Utilizando la función malloc() y otras que se presentan para la asignación de memoria dinámica, es posible definir arrays en tiempo de ejecución, denominados también arrays dinámicos.
Ejemplo:
int i, n_elementos, *a;
scanf(“%d “, &n_elementos);
a=(int *)malloc(n_elementos * sizeof(int));
for(i=0; i < n_elementos; i++)
scanf(“%d”, &a[i]);
31
M. C. Bertha López AzamarEl programa completo es el siguiente:#include<stdio.h>#include<conio.h>#include<stdlib.h>void main(){
int i, n_elementos, *a;printf("Introduce el número de elementos para crear el arreglo : ");scanf("%d", &n_elementos); /*Asignacion del espacio de memoria para el puntero */a=(int *)malloc(n_elementos * sizeof(int));
for(i=0; i < n_elementos; i++){
printf("%d.- ",i+1); scanf("%d", (a+i)); /*en el scanf se coloca (a+i) pero pudo
emplearse &a[i] también */ }
system("cls");for(i=0; i < n_elementos; i++){
printf("%d.- %d ",i+1, *(a+i)); /*aqui debe colocarse * antes */}getch();
}
32
M. C. Bertha López Azamar
#include<stdio.h>#include<conio.h>#include<stdlib.h>void llena(int *, int);void imprime(int *, int);void main(){ int i, n_elementos, *a; printf("Introduce el número de “); printf(“elementos para crear el arreglo : "); scanf("%d", &n_elementos); /*Asignacion del espacio de
memoria para el puntero */ a=(int *)malloc(n_elementos * sizeof(int));
llena(a, n_elementos);
system("cls");
imprime(a, n_elementos);
getch();}
Paso de parametros puntero
void llena(int *arr, int num){ int i; for(i=0; i < num; i++) {
printf("%d.- ",i+1); scanf("%d", (arr+i));
/*en el scanf se coloca (a+i) pero pudo emplearse &a[i] también */ }}
void imprime(int *arr, int num){ int i; for(i=0; i < num; i++) { printf("%d.- %d ",i+1, *(arr+i));
/*aqui debe colocarse * antes */ }}
top related