Documentos de Académico
Documentos de Profesional
Documentos de Cultura
7 Punteros Libro
7 Punteros Libro
UNAN – LEON
Departamento de Computación
Ing. En Sistemas de Información
Autor:
Ing: Karina Esquivel Alvarado.
Asignatura:
Programación Estructurada.
8.1 INTRODUCCIÓN
Los programas pueden crear variables globales o locales. Las variables declaradas globales
en sus programas se almacenan en posiciones fijas de memoria, en la zona conocida como
segmento de datos del programa, y todas las funciones pueden utilizar estas variables. Las
variables locales se almacenan en la pila (stack) y existen sólo mientras están activas las
funciones que están declaradas.
Todas estas clases de variables comparten una característica común: se definen cuando se
compila el programa. Esto significa que el compilador reserva (define) espacio para
almacenar valores de los tipos de datos declarados. Es decir, en el caso de las variables
globales y locales se ha de indicar al compilador exactamente cuántas y de qué tipo son las
variables a asignar. O sea, el espacio de almacenamiento se reserva en el momento de la
Compilación.
Sin embargo, no siempre es posible conocer con antelación a la ejecución cuanta memoria se
debe reservar al programa. En C, se asigna memoria en el momento de la ejecución en el
montículo o montón (heap), mediante las funciones malloc(), realloc( ), calloc( ) y free( ),
que asignan y liberan la memoria de una zona denominada almacén libre.
Por ejemplo, la sentencia: int asignatura [40]; reserva 40 enteros, un número fijo de
elementos. Los arrays son un método muy eficaz cuando se conoce su longitud o tamaño en el
momento de escribir el programa. Sin embargo, presentan un grave inconveniente si el
tamaño del array sólo se conoce en el momento de la ejecución. Las sentencias siguientes
producirían un error durante la compilación:
Ya que el compilador requiere que el tamaño del array sea constante. Sin embargo, en
numerosas ocasiones no se conoce la memoria necesaria hasta el momento de la ejecución.
2
Asignación Dinámica de Memoria en C
Por ejemplo, si se desea almacenar una cadena de caracteres tecleada por el usuario, no se
puede prever, a priori, el tamaño del array necesario, a menos que se reserve un array de
gran dimensión y se malgaste memoria cuando no se utilice. En el ejemplo anterior, si el
número de alumnos de la clase aumenta, se debe variar la longitud del array y volver a
compilar el programa. El método para resolver este inconveniente es recurrir a punteros y a
técnicas de asignación dinámica de memoria.
Por ejemplo:
int *p;
p = (int *) malloc(4);
3
Asignación Dinámica de Memoria en C
El operador unario sizeof se utiliza con mucha frecuencia en las funciones de asignación de
memoria. El operador se aplica a un tipo de dato (o una variable), el valor resultante es el
número de bytes que ocupa.
Al llamar a la función malloc( ) puede ocurrir que no haya memoria disponible, en ese caso
malloc( ) devuelve NULL.
El siguiente código utiliza malloc( ) para asignar espacio para un valor entero:
int *pEnt;
pEnt = (int *) malloc(sizeof(int));
Así, por ejemplo, para reservar memoria para un array de 100 números reales:
float *BloqueMem;
BloqueMem = (float*) malloc (100*sizeof(float));
4
Asignación Dinámica de Memoria en C
Ejemplo #1: Este programa lee una línea de caracteres, reserva memoria para un
buffer de tantos caracteres como los leídos y se copia en el buffer la cadena.
//cadena.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
char cad[21], *ptr ;
int lon ;
puts(“\nIntroduce una linea de texto:”) ;
gets(cad) ;
lon = strlen(cad); //Calcula la longitud de la cadena
ptr = (char *)malloc( (lon+1) * sizeof (char));
/*Devuelve un puntero que apunta a una sección de memoria capaz de contener la cadena de
longitud strlen ( ) más un byte extra por el carácter ‘\0’ al final de la cadena*/
strcpy (ptr, cad); //copia cad a nueva área de memoria
printf ("ptr--> %s\n\n",ptr); /*cad está ahora en ptr*/
free(ptr) ; /*libera memoria apuntada por ptr*/
}
Ejemplo de Salida:
5
Asignación Dinámica de Memoria en C
Ejemplo #2: Programa que crea un array de N valores de tipo entero de forma
dinámica.
//array_uni_dinamico.c
#include <stdio.h>
#include <stdlib.h>
void main()
{
int *ptr,nelem,i;
for(i=0;i<nelem;i++)
{
printf("Elemento[%d]:",i+1);
scanf("%d",(ptr+i));
}
printf("\n***ELEMENTOS DEL ARRAY***\n");
for(i=0;i<nelem;i++)
{
printf("%d ",*(ptr+i));
}
free(ptr); //Liberación de memoria apuntada por ptr
}
6
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
Un array bidimensional es, en realidad, un array cuyos elementos son arrays. Al ser el
nombre de un array unidimensional un puntero constante, un array bidimensinal será un
puntero a puntero constante (tipo **).
Para asignar memoria a un array multidimensional, se indica cada dimensión del array de igual
forma que se declara un array unidimensional.
Ejemplo #3: Programa en C que reserva memoria en tiempo de ejecución para una
matriz de n filas y para cada fila m elementos.
//array_bidi_dinamico.c
#include <stdio.h>
#include <stdlib.h>
void main()
{
int **p; //Puntero a Puntero
int n,m,i,j,k;
do
{
printf ("\nCuantas filas?");
scanf ("%d",&n);
} while(n <=1);
7
Asignación Dinámica de Memoria en C
//Reserva memoria para un array de n elementos, cada elemento es un puntero a entero (int *)
p = (int **) malloc(n * sizeof(int *));
if(p==NULL)
{
printf("Insuficiente Espacio de Memoria");
exit(-1);
}
for(i=0; i<n; i++)
{
printf("\n\nNumero de elementos de fila %d:", i+1) ;
scanf("%d",&m) ;
8
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
Además de la función malloc( ) para obtener bloques de memoria, hay otras dos funciones
que permiten obtener memoria libre en tiempo de ejecución, éstas son calloc( ) y realloc( ).
Con ambas se puede asignar memoria, lo que cambia en relación a la función malloc( ) es la
forma de transmitir el número de bytes de memoria requeridos. Ambas devuelven un
puntero al bloque asignado de memoria. El puntero se utiliza para referenciar el bloque de
memoria. El puntero que devuelven es del tipo void *.
9
Asignación Dinámica de Memoria en C
La función calloc( ) está declarada en el archivo de cabecera stdlib.h, por lo que será
necesario incluir ese archivo de cabecera en todo programa que llame a la función. Se puede
reservar memoria dinámicamente para cualquier tipo de dato, incluyendo char, float, arrays,
estructuras e identificadores de typedef.
Ejemplo #4: Este programa lee una línea de caracteres, reserva memoria con la
función calloc( ) para un buffer de tantos caracteres como los leídos y se copia en el
buffer la cadena.
//funcion_calloc.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *c, B[121];
puts("Introduce una cadena de caracteres:");
gets (B);
/*Se reserva memoria para el número de caracteres + 1 para el carácter*/
c = (char*) calloc (strlen(B)+1,sizeof( char));
//Copia la cadena leída en c
strcpy(c,B);
printf("\nc--> %s\n",c);
//Liberación de Memoria
free(c);
}
10
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
//calloc_fn.c
#include <stdlib.h>
#include <stdio.h>
void main(void)
{
float *pf=NULL;
int num, i;
do
{
printf("Cuantos datos en el array?");
scanf ( "%d",&num) ;
}while (num<1);
11
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
Esta función también es para asignar un bloque de memoria libre. Tiene una variación
respecto a malloc( ) y calloc( ), permite ampliar un bloque de memoria reservado
anteriormente.
12
Asignación Dinámica de Memoria en C
Ejemplo #6: Programa en C que permite reservar memoria para una cadena y a
continuación, ampliar para otra cadena más larga utilizando la función realloc( ).
//realloc_fn.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main( )
{
char *cadena;
int tam;
tam = (strlen("Practicas")+ 1) * sizeof (char);
cadena = (char *) malloc (tam);
strcpy (cadena,"Practicas") ;
puts (cadena) ;
//Ampliación del bloque de memoria
tam += (strlen("Profesionales\n")+ 1)* sizeof (char);
cadena = (char * ) realloc (cadena, tam);
strcat (cadena," Profesionales\n");
puts(cadena);
//Liberación de memoria
free (cadena) ;
}
Ejemplo de Salida:
La gestión de listas y tablas mediante arrays es una de las operaciones más usuales en
cualquier programa. La asignación de memoria para arrays es, en consecuencia, una de las
tareas que es preciso conocer en profundidad.
Ejemplo #7: Este programa lee n líneas de texto, reserva memoria según la longitud de
la línea leída, cuenta las vocales de cada línea e imprime cada línea y el número de
vocales que tiene. El programa declara char *cad[N] como array de punteros a char,
de tal forma que en la función entrada( ) se reserva memoria, con malloc( ), para cada
línea de texto.
13
Asignación Dinámica de Memoria en C
//cuenta_vocales.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define N 10
//Prototipos de Funciones
void salida(char *[ ], int *);
void entrada(char *[ ]);
int vocales(char *) ;
void main( )
{
char *cad[N];
int j, voc[N];
//Función para leer cadenas de caracteres
entrada (cad) ;
//Cuenta de vocales por cada cadena
for(j=0; j<N; j++)
voc[j] = vocales(cad[j]);
salida(cad, voc) ;
}
14
Asignación Dinámica de Memoria en C
int j;
puts ("\n\tSalida de las cadenas junto al numero de vocales") ;
for (j=0; j<N; j++)
{
printf ("Cadena [%d]: %s tiene %d vocales\n",j+1,cd[j], v[j]);
}
}
15
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
Los punteros a estructuras se declaran igual que los punteros a otros tipos de datos. Para
referirse a un miembro de una estructura referenciado por un puntero es necesario utilizar
el operador “->”.
Ejemplo #8: Programa que lee los datos de una estructura “Deportista” utilizando el
operador “->”.
//deportista.c
#include<stdio.h>
#include<stdlib.h>
struct Deportista
{
char nombre [30];
float altura;
float peso;
};
16
Asignación Dinámica de Memoria en C
void main( )
{
struct Deportista d,*dep;
dep = &d;
printf("Nombre: ");
scanf("%s",dep->nombre);
printf("Altura: ");
fflush(stdin);
scanf("%f",&dep->altura);
printf("Peso: ");
scanf("%f",&dep->peso);
Ejemplo de Salida:
Ejemplo #9: Este programa asigna memoria dinámica para un array de 3 estructuras
de tipo Estudiante y calcula cuál es el estudiante que obtuvo la mayor nota.
//nota_mayor.c
#include<stdio.h>
#include<stdlib.h>
struct Estudiante
{
char nombre[30];
int nota;
};
17
Asignación Dinámica de Memoria en C
void main()
{
struct Estudiante *est;
int i=1,j=1,pos,may;
18
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
19
Asignación Dinámica de Memoria en C
else
{
for(n=1;n<=nest;n++)
{
printf("Nombre Estudiante: ");
fflush(stdin);
gets(est[n].nombre);
do
{
printf("Sexo(f/m): ");
fflush(stdin);
scanf("%c",&est[n].sexo);
}
while((est[n].sexo !='f' && est[n].sexo!='F') && (est[n].sexo !='m' && est[n].sexo!='M'));
if((est[n].sexo=='f') || (est[n].sexo=='F'))
nef++;
if((est[n].sexo=='m') || (est[n].sexo=='M'))
nem++;
printf("Nota: ");
scanf("%d",&est[n].nota);
20
Asignación Dinámica de Memoria en C
Ejemplo de Salida:
Se puede asignar espacio para cualquier objeto dato de C. Las reglas para utilizar las
funciones malloc( ), calloc( ), realloc( ) y free( ) como medio para obtener/liberar espacio
de memoria son las siguientes:
2. Las funciones malloc( ) , calloc() , realloc( ) devuelven el tipo void *, lo cual exige
hacer una conversión al tipo del puntero.
4. El operador sizeof permite calcular el tamaño de un tipo de objeto para el que está
asignando memoria.
21
Asignación Dinámica de Memoria en C
Ejemplo:
struct punto
{
float x,y,z;
}
struct punto *p = (struct punto *)malloc (sizeof(struct punto));
void main()
{
struct complejo *pz;
int n;
22
Asignación Dinámica de Memoria en C
scanf("%d",&n);
/*Puntero a estructura complejo*/
/*Asigna memoria para un array de tipo complejo*/
pz = (struct complejo *)calloc(n,sizeof(struct complejo));
if (pz == NULL)
{
puts ("Error de asignación de memoria.") ;
exit(-1);
}
}
23