Unidad 3
Punteros
Objetivos del Aprendizaje
• Definir qué son los punteros y describir su rol en la
resolución de problemas.
• Discutir los conceptos de punteros, variables,
direcciones de memoria y referencias.
• Explicar cómo hacer declaraciones de punteros.
• Discutir el uso de los punteros para
parámetros a las funciones por referencias.
pasar
• Explicar funciones que pueden recibir arreglos
unidimensionales como argumentos a través de
punteros.
Fundamentos de Punteros
• Un puntero es una variable en C que representa una
dirección de un elemento de datos en la memoria.
• Los punteros son importantes porque:
• Son útiles para crear aplicaciones
• Se pueden usar para pasar argumentos a funciones por
referencia.
• Son útiles para acceder a elementos individuales de
estructuras de datos tales como arreglos, estructuras y
tipos de datos definidos por el usuario.
• Se pueden usar para realizar asignación dinámica de
memoria, es decir, reservar la cantidad de memoria que
requiera la estructura de datos, en vez de estar limitado
por arreglos de dimensiones y tamaño fijos.
Asignación de Memoria en Declaración de Variable
La declaración int x = 5 solicita al compilador:
• Asignar o realmente reservar memoria para
almacenar el entero.
• Asociar el nombre x con la posición de memoria.
• Almacenar el valor entero 5 en esa posición.
Nombre de
la variable
x
5
Dirección de la variable
43658
Valor en la posición
(Contenido de la variable)
Asignar dirección de variable a otra variable
Siendo…
int x = 5;
var_nombre = &x;
• &x se refiere a la dirección de memoria de x y no a su
valor.
• var_nombre ahora apunta a la dirección de la ubicación
donde el valor de x está almacenado.
• Es posible acceder al valor de la variable x usando el
operador de indirección o de 'desreferencia‘ con:
*var_nombre.
Dirección de x
var_nombre
Valor de x =5,
x
Declaración de Punteros
• Declaración de puntero:
tipo-de-dato *variable_puntero;
- tipo-de-dato: tipo de dato del objeto.
- variable_puntero: nombre de la variable puntero que se
está declarando
- El carácter * debe preceder el nombre de la variable puntero.
• Ejemplo de declaraciones válidas de punteros:
int *var_name;
float *temp;
char *pval;
• Se
puede inicializar una variable puntero en la misma
declaración.
int x, y;
int *var_name = &x;
Usar Punteros para pasar Argumentos a Funciones
• En C, el método normal de pasar argumentos a
funciones es a través de parámetros por valor.
• Cuando se pasa un argumento como un valor a una
función, se hace una copia del elemento de dato dentro
de la función.
• Dentro de la función todas las referencias a los
argumentos a través de los parámetros formales son
dirigidos a la copia.
• De manera que si se modifica este elemento de dato,
es la copia dentro de la función la que es modificada y
no la usada en la llamada.
Uso de Punteros...Ejemplo 1
Intercambiar el valor de dos variables
intercambiar(&x, &y);
La función intercambiar se define como:
void intercambiar(int *p, int *q){
int temp;
temp = *p;
*p = *q;
*q = temp;
return;
}
Uso de Punteros...Ejemplo 2
Sumar los números impares de un arreglo
• Función main()
int main(){
int vector[100];
…
printf(“La suma de los datos impares es \
%d\n”, sum_impar(vector));
…
}
• Prototipo de función y argumento formal a la función:
int sum_impar(int vect[]);
int sum_impar(int *vect);
Pasar Arreglos a scanf()
• Para leer variables int, float, y char se debe
usar la función scanf().
• La variable debe estar precedidas por el carácter &.
• Ejemplo:
int x; float p; char ch;
scanf(“%d %f %c”, &x, &p, &ch);
• La función scanf require la dirección de manera
que los elementos de datos se puedan almacenar en
la ubicación correcta.
• La función scanf no requiere el carácter & para
leer cadenas en un arreglo.
char fnombre[45];
scanf(“%s”, fnombre);
Aritmética de Direcciones
• Un nombre de arreglo es realmente un puntero al primer
elemento del arreglo.
• Si caja es un arreglo unidimensional, la dirección del
primer elemento puede ser referenciado como
&caja[0] o sólo caja.
• Se tienen dos formas de escribir las direcciones de los
elementos de un arreglo:
- &caja[i] y
- caja + i.
• El subíndice i se denomina desplazamiento (offset).
Búsqueda Lineal
Planteamiento:
Buscar un elemento en el arreglo
• La búsqueda se comienza desde el primer
elemento en el arreglo y se continúa buscando a
través del arreglo hasta que el elemento se
encuentre o hasta que se haya recorrido todo el
arreglo.
• Se denomina búsqueda lineal, porque se busca
desde el primer elemento hasta el último
elemento, o hasta que el elemento se encuentra
en el arreglo.
Búsqueda Lineal...2
int busqueda(int *caja,int n, int num){
/* n es el tamaño del arreglo, num es el
número buscado */
int k;
k=0;
while(k<n){
if(*(caja+k) ==num)
return (k);
else
k++;
}
return(-1);
}
Resumen
• Se definió qué son los punteros y se describió su rol
en la resolución de problemas.
• Se discutieron los conceptos de punteros, variables,
posiciones de memorias y referencias.
• Se explicó cómo hacer declaraciones de punteros
• Se discutió el uso de punteros para pasar parámetros
a funciones por referencia.
• Se explicaron las funciones que pueden recibir
arreglos unidiemensionales como argumentos a
través de punteros.
Punteros Avanzados
Objetivos del Aprendizaje
• Explicar la aritmética de direcciones.
• Describir un puntero a puntero y un arreglo de
punteros.
• Discutir cómo declarar y usar punteros con
estructuras.
• Explicar
cómo
pasar
funciones
como
argumentos a otras funciones a través de
punteros.
Introducción
• Los punteros son importantes en cualquier esfuerzo
para resolver problemas.
• Se puede declarar un puntero para cualquier tipo de
dato.
• C permite que el programador declare tipos de datos
definidos por el usuario.
• C permite usar punteros a estructuras.
Aritméticas de Direcciones
• Un tipo de dato es un conjunto de valores y las
operaciones definidas sobre ellos.
• Un puntero se declara como int *ptr; indicando
que ptr es una variable que pertenece al tipo de dato
int *.
• C considera sólo dos operaciones sobre las variables
punteros: adición y resta.
• Para la la aritmética de direcciones, el tipo de dato al
que el puntero está asociado es importante.
• El tamaño del tipo de dato es lo que se usa en el
cálculo de la expresión que involucra aritmética de
direcciones.
Aritméticas de Direcciones
• La aritmética de direcciones se usa para mover el puntero
a la próxima posición en la memoria y acceder al elemento
almacenado en esa posición.
• En este caso la
fundamental.
asignación de memoria contigua es
• La aritmética de direcciones normalmente aplica cuando se
usa con arreglos.
• C integra punteros, arreglos y aritmética de direcciones.
• Los arreglos en C implícitamente usan aritmética de
direcciones para acceder a sus elementos.
• La aritmética de direcciones no se puede usar con tipos de
datos como int o char porque el contenido de la próxima
posición no se conoce.
Direcciones de la Variable Puntero ptr
Elemento
Dirección de
Memoria de la
Posición
10
1028
20
1030
30
1032
40
1034
50
1036
60
1038
70
1040
80
1042
90
1044
100
1046
arreglo
ptr
Dos Variables Punteros
Elemento
Dirección de
Memoria de la
Posición
10
1028
20
1030
30
1032
40
1034
50
1036
60
1038
70
1040
80
1042
90
1044
100
1046
ptr1
ptr2
Puntero a Puntero
Dirección y Contenido de una Variable Puntero
x
10
508
Posición de una Variable Puntero y su Contenido
x
y
10
508
508
1024
Posición de Variables Puntero y su Contenido
x
10
508
y
508
1024
z
1024
3308
Arreglo de Punteros
• Un arreglo bidimensional se define como un arreglo
unidimensional de punteros:
tipo-de-dato *arreglo[c_expr];
• Un arreglo de bidimensional se define como:
tipo-de-dato arreglo[c_expr1][ c_expr2];
• Las dos definiciones anteriores son equivalentes.
• El tamaño de un arreglo es siempre una constante,
representada anteriormente por c_expr.
• Los subíndices de un arreglo pueden ser de tipos
integrales int y char.
• El tipo de dato float no se puede usar como
subíndice de arreglos.
Arreglo de Punteros...2
• Se puede extender la definición del uso de punteros para arreglos
multi-dimensionales como:
data-type *array[c_expr1][c_expr2]…[c_exprn-1];
para un arreglo de n dimensiones.
• Note que tiene una dirección menos. Una definición de arreglo
equivalente es:
data-type *array[c_expr1][c_expr2]…[c_exprn];
• Un arreglo bidimensional de cinco filas y 25 columnas de enteros
se define como:
int *x[5];
Arreglo de Punteros...3
• Ejemplo de arreglo multidimensional:
Arreglo tridimensional de enteros de tamaño 5 x 10 x 15 se
define como un arreglo bidimensional de punteros:
int *y[5][10];
• Un elemento individual de un arreglo tridimensional,
convencionalmente se accede como y[i][j][k], se
puede acceder también como:
*(y[i][j] + k)
• Los arreglos de punteros se usan para almacenar cadena
de caracteres, cada elemento del arreglo es un puntero a
carácter que define el principio de una cadena separada:
char *a[10];
Uso de Punteros a Cadenas de Caracteres...Ejemplo 1
Considere cuatro cadenas de caracteres.
Se requiere hacer lo siguiente:
• Comparar la primera cadena de caracteres con
todos las otras cadenas de caracteres y verificar
si la primera cadena de caracteres es mayor,
menor o igual a las otras cadenas de caracteres.
Mostrar el resultado .
• Concatenar las cadenas de caracteres con la
palabra ’color’.
Uso de Punteros a Cadenas de Caracteres...Ejemplo 1
En el ejemplo:
• Se usa la librería de funciones de cadenas de
caracteres (string) definidas en <string.h>,
• Se asigna memoria dinámicamente.
Se usan las siguientes cuatro funciones de cadenas
de caracteres:
• int strlen(const char *): Toma un puntero
a una cadena, y retorna la longitud de la cadena.
• char * strcpy(char *, const char *):
Toma dos cadenas y copia la segunda cadena
dentro de la primera cadena.
Uso de Punteros a Cadenas de Caracteres
• int strcmp(const char *, const char *):
Toma dos cadenas y retorna:
0 si ambas cadenas son iguales,
< 0 si la primera cadena es menor que la segunda
> 0 si la primera cadena es mayor que lal segunda.
• char * strcat(char *, const char *):
Toma dos cadenas y concatena (une) las dos
cadenas agregando la segunda cadena a la primera.
Punteros a Estructura
• Los punteros pueden apuntar a estructuras.
• Ejemplo:
struct persona{
char nombre[45];
int edad;
float peso;
};
struct persona *sptr;
• Si sptr es la variable puntero a la estructura, se
puede acceder a cada componente individual de la
estructura de la siguiente forma:
sptr->nombre
sptr->edad
sptr->peso
Punteros a Funciones
• Es posible definir punteros a una función, la cual
puede ser colocada en arreglos, pasada a
funciones y retornar de las funciones.
• Una función puede ser pasada como un argumento
a otra función y para eso se usa el puntero a una
función.
• Tal situación se presenta cuando una función,
referida como la primera función, realiza tareas
usando otra función.
Punteros a Funciones...2
Se tienen cuatro funciones independientes que realizan
cálculos diferentes dependiendo de la entrada:
• Determinar la raíz cuadrada de un entero
• Determinar la raíz cúbica de un entero
• Determinar si un número entero es primo
• Determinar si un entero es un palíndrome
Punteros a Funciones...Ejemplo 1
int raizCuadrada(int x){
int sqrt=0;
sqrt =(int) pow (x,0.5);
return(sqrt);
}
void generarTabla(int (*fptr)(int)){
int i;
for(i=1;i<=1000;i++)
printf("%d\t%d\n",i,(*fptr)(i));
}
main(){
generarTabla(raizCuadrada);
}
Resumen
• Se explicó la aritmética de direcciones.
• Se estudió el concepto de puntero a
puntero y arreglo de punteros.
• Se explicó cómo declarar y usar punteros
con estructuras.
• Se estudió cómo pasar funciones como
argumentos a otras funciones a través de
punteros.
Descargar

Document