0% encontró este documento útil (0 votos)
13 vistas26 páginas

A Punt Adores

El documento aborda la manipulación de memoria en el lenguaje de programación C, diferenciando entre memoria estática y dinámica. Se explican conceptos clave como apuntadores, su definición, inicialización y aritmética, así como funciones de gestión de memoria como malloc, calloc, realloc y free. Se enfatiza la importancia de liberar la memoria asignada para evitar fugas y asegurar la eficiencia del programa.

Cargado por

aij305230
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
13 vistas26 páginas

A Punt Adores

El documento aborda la manipulación de memoria en el lenguaje de programación C, diferenciando entre memoria estática y dinámica. Se explican conceptos clave como apuntadores, su definición, inicialización y aritmética, así como funciones de gestión de memoria como malloc, calloc, realloc y free. Se enfatiza la importancia de liberar la memoria asignada para evitar fugas y asegurar la eficiencia del programa.

Cargado por

aij305230
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Universidad Autónoma de Baja California

Facultadad de Química e Ingeniería


ISyTE

Lenguaje C
Unidad 5: Memoria Dinámica
Memoria Dinámica 2

Al realizar un programa en la computadora, si se quiere que el programa


sea lo más eficiente, es necesario aprender a manipular la memoria, la
cual existen dos tipos:

■ Memoria Estática. (stack)


■ Memoria Dinámica. (heap)
Memoria Estática 3

Esta memoria se utiliza al momento de compilar, todos los elementos se


le asignan un espacio de memoria continua, el tamaño de asignación es
conocido por el compilador.

Tambien conocido como Stack Memory o Memoria de Alojamiento


Temporal ya que al terminar de usarla automáticamente se borra.
Memoria Dinámica 4

Esta memoria se utiliza durante la ejecución del código, el


programador tiene la obligación de asignar un espacio en memoria y de
liberar ese espacio una vez que ya no se utilice.

A diferencia de la memoria estática, hay que tener cuidado ya que esta


memoria es compartida por todos los programas y si no se asigna y libera
correctamente puede haber fugas de memoria.
Apuntadores 5

Una de las características más poderosas del lenguaje C es dominar la


utilización de los apuntadores, ya que permiten optimizar el tiempo de
ejecución al simular llamadas por referencia, manipular estructuras de
datos dinámicamente (crecer o encogerse ) al momento de ejecución.
Definición e Inicialización 6

Los apuntadores son variables cuyo valores son direcciones de memoria.


Por lo general una variable contiene directamente un valor especifico pero
los apuntadores contienen la dirección de memoria de una variable
que contiene un valor especifico.
Definición e Inicialización 7

De lo anterior, el nombre de una variable hace referencia directa a un


valor y el apuntador hace referencia indirect a a un valor.

El proceso de referenciar un valor a través de un apuntador se le llama


indirección

ptrcuenta cuenta

• 7
Definición e Inicialización 8

Los apuntadores como todas las variables deben de definirse antes de que
se puedan utilizar

Definir apuntadores

tipo_dato ∗ nombre_variable ;
Ejemplo

int ∗ ptrcuenta ;
Los apuntadores pueden definirse para apuntar a objetos de cualquier
tipo de datos.
Definición e Inicialización 9

Los apuntadores se pueden inicializarse en el momento en que se


definen o en una instrucción de asignación después, se puede
inicializar en 0 o NULL o en una dirección

Ejemplo
i n t y = 5 ; // d e f i n i c i o n y a s i g n a c i o n
i n t ∗ p t r y ; // d e f i n i c i o n
p t r y = &y ; // a s i g n a c i o n

El operador & en este contexto, es utilizado para obtener la dirección de


memoria de una variable que esta en la memoria estática.
Definición e Inicialización 10

Del ejemplo anterior la representación en memoria es la siguiente

ptry y

0x 123ff &y 5

0x 123ff
El operador de dirección (&) no se puede aplicar a un valor constante o
expresiones.
Definición e Inicialización 11

El operador * por lo general llamado operador de indirección o de


desreferencia, devuelve el valor del objeto que apunta su operando (el
apuntador)

Ejemplo
#include < s t d i o . h>

i n t main ( )
{
int y = 5;
int ∗ ptry ;
p t r y = &y ;

p r i n t f ( " y= %d \ n D i r e c c i o n de Y = %p\n " , y ,& y ) ;


p r i n t f ( " p t r Y= %p \ n v a l o r D i r e c c i o n de p t r Y = %d " , p t r y , ∗ p t r y ) ;

return 0;
}
Definición e Inicialización 12

f l o a t ∗X=0; // d e f i n i c i o n de apuntador e i n i c i a l i z a r en nulo


f l o a t y =10; // d e f i n i r e i n i c i a l i z a r v a r i a b l e
// &y l a d i r e c c i o n de memoria de y
X=&y ; // a s i g n a r una d i r e c c i o n de memoria a un apuntador
// ∗X acceder a l v a l o r que apunta l a memoria
p r i n t f ( " [%p ] %f \n " , ( v o i d ∗ )X, ∗ X ) ; // i m p r i m i r memoria y su v a l o r
Aritmética apuntadores 13

El lenguaje C permite sumar o restar cantidades enteras al puntero, para


que apunte a una dirección diferente esto se le conoce como aritmética
de punteros

Operador Descripción
++ incrementa un espacio
-- decrementa un espacio
+=int incrementa int espacios
-=int decrementa int espacios
*apuntador obtiene el valor de la dirección que apunta
los operadores se resuelven de izquierda a derecha
Aritmética apuntadores 14

#include < s t d i o . h>


i n t main ( v o i d )
{
i n t a [ 5 ] = { 1 0 , −2 0 , 3 0 , −4 0 , 5 0 } ;
// a s i g n a r e l e s p a c i o de memoria a l apuntador
i n t ∗ ptrA = a ;

p r i n t f ( " [%p ] d i r e c c i o n de a \n " , ( v o i d ∗)&a ) ;


p r i n t f ( " [%p ] d i r e c c i o n de p t r A \n " , p t r A ) ;

f o r ( i n t i =0; i <5;++ i )
{
// e q u i v a l e n t e a hacer ptrA [ i ] o a [ i ]
p r i n t f ( " [%p ] %d\n " , ( v o i d ∗ ) ( p t r A+i ) , ∗ ( p t r A+i ) ) ;
}
return 0;
}

Los corchetes de un arreglo, es una abreviación de la aritmética de


punteros
Declaraciones Avanzadas 15

Crear y mantener estructuras de datos dinámicas requiere de la


asignación de la memoria dinámica(heap), es decir la habilidad de un
programa de obtener mas espacio de memoria en tiempo de ejecución,
para almacenar nuevos nodos y liberar espacio que ya no sea necesario.

Para lograrlo es necesario el uso de las librerías stdlib.h ya que nos


proporcionan las herramientas necesarias para la manipulación y
liberación de memoria.
Declaraciones Avanzadas 16

Las siguientes funciones se utilizan para la manipulación de memoria.


Función Descripción
malloc Aloja un bloque de memoria del tamaño del tipo de dato en bytes
calloc Aloja bloque de memoria para un numeros de objetos de tamaño del tipo de dato en bytes
realloc Asigna mas espacio de memoria si no es suficiente en bytes
free Libera el espacio de memoria
Malloc 17

Significa Memory Allocation o en español alojamiento de memoria, esta


función aloja un bloque de memoria del tamaño del tipo de dato que se
va almacenar de manera no inicializada. Si el alojamiento fue existoso
regresa un apuntador que contiene la dirección de memoria de
dicho bloque, de lo contrario regresa NULL

Siempre se debe utilizar free al terminar de utilizar el apuntador


para liberar la memoria.

Sintaxis Malloc

v o i d ∗ malloc ( s i z e _ t s i z e ) ;
Malloc 18

Ejemplo Malloc
#include < s t d i o . h>
#include < s t d l i b . h>
#include < s t r i n g . h>
i n t main ( )
{
// alocamos un bloque de memoria de 10 e n t e r o s
i n t ∗ p t r A = ( i n t ∗ ) malloc ( 1 0 ∗ s i z e o f ( i n t ) ) ;
i f ( ! ptrA )
p r i n t f ( "No s e pudo a l o j a r memoria p a r a e l a p u n t a d o r \n " ) ;
f o r ( i n t i =0; i <10; i ++)
{
// e q u i v a l e n t e a ptrA [ i ] = i ∗10;
∗ ( p t r A+i ) = i ∗ 1 0 ;
}
f o r ( i n t i =0; i <10; i ++)
{
p r i n t f ( " [%p ] %d\n " , p t r A+i , ∗ ( p t r A+i ) ) ;
}

// siempre l i b e r a r memoria s i se usa malloc , c a l l o c , r e a l l o c


f r e e ( ptrA ) ;
return 0;
}
Calloc 19

Significa Contiguous Allocation o en español alojamiento contiguo , esta


función aloja un bloque de memoria del tamaño de multiples objetos de
un tipo de dato inicializada en 0. Si el alojamiento fue existoso regresa
un apuntador que contiene la dirección de memoria de dicho
bloque, de lo contrario regresa NULL

Siempre se debe utilizar free al terminar de utilizar el apuntador


para liberar la memoria.

Sintaxis Calloc
v o i d ∗ c a l l o c ( s i z e _ t num , s i z e _ t s i z e ) ;
Calloc 20

Ejemplo calloc
#include < s t d i o . h>
#include < s t d l i b . h>
#include < s t r i n g . h>
i n t main ( )
{
// alocamos un bloque de memoria de 10 e n t e r o s
i n t ∗ ptrA = ( i n t ∗) c a l l o c (10 , s i z e o f ( i n t ) ) ;
i f ( ! ptrA )
p r i n t f ( "No s e pudo a l o j a r memoria p a r a e l a p u n t a d o r \n " ) ;
f o r ( i n t i =0; i <10; i ++)
{
// e q u i v a l e n t e a ptrA [ i ] = i ∗10;
∗ ( p t r A+i ) = i ∗ 1 0 ;
}
f o r ( i n t i =0; i <10; i ++)
{
p r i n t f ( " [%p ] %d\n " , p t r A+i , ∗ ( p t r A+i ) ) ;
}

// siempre l i b e r a r memoria s i se usa malloc , c a l l o c , r e a l l o c


f r e e ( ptrA ) ;
return 0;
}
Free 21

Esta función se utiliza para des-alojar la memoria que apunta un


apuntador, para luego poder ser utilizada.

Sintaxis free

void free ( void ∗ p t r ) ;


Regla de dedo: por cada llamada de malloc o calloc se debe de usar
un free
Realloc 22

Esta función se utiliza para cuando se ocupe mas memoria de lo que


previamente se había alojado, solamente puede re-alojar memoria si
el apuntador previamente había sido alojado por malloc o calloc

Sintaxis realloc
void ∗ r e a l l o c ( void ∗ ptr , size_t nuevo_size ) ;
Realloc 23

Ejemplo realloc
#include < s t d i o . h>
#include < s t d l i b . h>
#include < s t r i n g . h>
i n t main ( v o i d )
{
// alocamos un bloque de memoria de 3 e n t e r o s
i n t ∗ ptrA = ( i n t ∗) c a l l o c (3 , s i z e o f ( i n t ) ) ;
i f ( ! ptrA )
p r i n t f ( "No s e pudo a l o j a r memoria p a r a e l a p u n t a d o r \n " ) ;
p r i n t f ( " D i r e c c i o n de memoria a l o j a d a \n " ) ;
f o r ( i n t i =0; i <3; i ++)
{
p r i n t f ( " [%p ] \ n " , ( v o i d ∗ ) ( p t r A+i ) ) ;
}

p t r A = r e a l l o c ( ptrA , 8 ∗ s i z e o f ( i n t ) ) ;

p r i n t f ( " D i r e c c i o n de memoria r e −a l o j a d a \n " ) ;


f o r ( i n t i =0; i <8; i ++)
{
p r i n t f ( " [%p ] \n " , ( v o i d ∗ ) ( p t r A+i ) ) ;
}
// siempre l i b e r a r memoria
f r e e ( ptrA ) ;
return 0;
}
Ejemplo 2 24

Ejemplo 2
#include < s t d i o . h>
#include < s t d l i b . h>
i n t main ( )
{
i n t ∗ p t r A = ( i n t ∗ ) malloc ( 1 0 ∗ s i z e o f ( i n t ) ) ;
i n t c o n t a d o r =0;
i n t maximo =10;
i f ( ! ptrA )
p r i n t f ( "No s e pudo a l o j a r memoria p a r a e l a p u n t a d o r \n " ) ;
f o r ( i n t i =0; i <maximo ; i ++)
{
∗ ( p t r A+i ) = i ∗ 1 0 ;
c o n t a d o r ++;
}
p r i n t f ( " \n " ) ;
i f ( c o n t a d o r == maximo )
{
// incrementar e l bloque de memoria de ptrA
p t r A = ( i n t ∗ ) r e a l l o c ( ptrA , maximo ∗2∗ s i z e o f ( i n t ) ) ;
}
i f ( ! ptrA )
p r i n t f ( "No s e pudo a l o j a r memoria p a r a e l a p u n t a d o r \n " ) ;
f o r ( i n t i =10; i <maximo ∗ 2 ; i ++)
{
∗ ( p t r A+i ) = i ∗ 1 0 ;
c o n t a d o r ++;
}
f o r ( i n t i =0; i <maximo ∗ 2 ; i ++)
{
p r i n t f ( " [%p ] %d\n " , ( v o i d ∗ ) ( p t r A+i ) , ∗ ( p t r A+i ) ) ;
}
// siempre l i b e r a r memoria
f r e e ( ptrA ) ;
return 0;
}
Apuntador a funciones 25

El uso de apuntadores, nos permite manipular libremente la memoria, por


ejemplo si quisiéramos tener un arreglo de funciones o pasarle a otra
función como parámetro una función.

arreglos de funciones
// supongamos que tenemos 3 f u n c i o n e s y l a s queremos guardar en un a r r e g l o
v o i d ( ∗ f u n c i o n e s [ 3 ] ) ( i n t [ ] , i n t ) ={ p r i n t _ a r r e g l o , menormayor , mayormenor } ;

podemos usar typedef para definir el prototipo de la función como un


tipo de dato y reducir la sintaxis al leerlo

arreglos de funciones
typedef void (∗ fu nc_a rra y ) ( i n t [ ] , i n t ) ;

// supongamos que tenemos 3 f u n c i o n e s y l a s queremos guardar en un a r r e g l o


f u n c _ a r r a y f u n c i o n e s [ 3 ] ={ p r i n t _ a r r e g l o , menormayor , mayormenor } ;
Apuntador a funciones 26

La llamada de la función se hace como si estuvieramos accediendo a un


elemento de un arreglo común.

arreglos de funciones llamada


// supongamos que A es un a r r e g l o de 10 elementos i n t A[ 1 0 ]
funciones [ 0 ] (A, 1 0 ) ;
funciones [ 1 ] (A, 1 0 ) ;
funciones [ 0 ] (A, 1 0 ) ;
funciones [ 2 ] (A, 1 0 ) ;

También podría gustarte