Skip to content
This repository has been archived by the owner on Dec 31, 2024. It is now read-only.

Commit

Permalink
Merge pull request #88 from TeenBiscuits/t2-gestión-dinámica-de-memor…
Browse files Browse the repository at this point in the history
…ia-punteros

T2 Gestión Dinámica de Memoria Punteros.
  • Loading branch information
TeenBiscuits authored Feb 28, 2024
2 parents 067e552 + b781e14 commit 3270330
Show file tree
Hide file tree
Showing 3 changed files with 343 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/pro.tree
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ SPDX-License-Identifier: GPL-3.0-only
<toc-element topic="Bloque-4.md"/>
</toc-element>
<toc-element toc-title="Pro II">
<toc-element topic="Tema-2.md"/>
<toc-element toc-title="Próximamente..."/>
</toc-element>
<toc-element topic="Bibliografia.md"/>
Expand Down
341 changes: 341 additions & 0 deletions docs/topics/Tema-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
<!--
SPDX-FileCopyrightText: 2024 Pablo Portas López
SPDX-License-Identifier: CC-BY-NC-4.0
-->

<tip>Copyright © 2024 Pablo Portas López</tip>

# Tema 2 - Gestión dinámica de memoria

<tldr>Punteros en profundidad, las variables dinámicas, direcciones de memoria y la gestión de la memoria (pila (stack) y montículo (heap)).</tldr>

## Organización de la memoria de un programa

Existen dos lugares en memoria para almacenar elementos: la pila (**stack**) y el montículo (**heap**).

| Nombre | Función |
|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Código | El código compilado. |
| Datos estáticos | Datos estáticos compilados. |
| Pila (stack) | Se utiliza para la llamada de funciones y punteros, ahí se almacenan sus direcciones, parámetros, constantes locales, etc... |
| ... | Espacio para crecer. |
| Montículo (heap) | Parte de la memoria que no está ligada a lo guardado en la pila, se utiliza para las variables dinámicas, la memoria se reserva cuando se solicita (```malloc```). |


## Definición de variables de tipo puntero

<deflist>
<def title="Punteros en C">

- Un puntero es un **tipo básico** en C (como ```int```, ```bool```, ```float```, ```etc```.) y como tal **ocupa en memoria una cantidad determinada** (generalmente 4 bytes).
- Una variable de tipo puntero **contiene una dirección de memoria** en la cual se almacena **una variable de otro tipo**.
- Las variables de tipo puntero en C se declara para que apunte a un tipo particular de datos (```int```, ```float```, ```etc```.) y no puede apuntar a ningún otro.

</def>
<def title="Sintaxis">
<code-block lang="C">
// Estructura
typedef tipoApuntado* tipoPuntero
// Otro ejemplo
typedef int* tPEntero
// tPEntero es un puntero a int
tPEntero P
// Has declarado un puntero P
// que no apunta a nada todavía
</code-block>
</def>
</deflist>

## Reserva y destrucción dinámica de memoria

### Inicialización de punteros

```C
typedef int* tPEntero;
tPEntero P1;
int* P2;
```

- ```tPEntero``` las variables declaradas con este nuevo tipo contendrán direcciones de memoria de **variables enteras**.
- ```P1``` se **reserva memoria** en la **pila** para guardar una **dirección de memoria** (4 bytes) que apuntara a un entero del **montículo**.
- No es necesario definir un tipo para declarar un entero (como se ve en ```int* P2```), pero se recomienda hacerlo de esta manera
para **aumentar la abstracción**.
- La memoria es reservada, pero **no se elimina los contenidos que ya hubiera en esa zona**. Inicialmente, ```P1``` o ```P2``` contendrá un valor _basura_.

Utilizar punteros con contenido _basura_ puede tener **efectos fatales**. Por lo tanto, es mejor inicializarlos a nulo ```P = NULL;```

<warning>En el lenguaje C este valor nulo se representa con la constante <b>NULL</b>.</warning>

### La variable dinámica

#### Creación de una variable dinámica

Para crear la variable dinámica apuntada por un puntero se utiliza el operador ```malloc``` definido en el archivo de cabecera ```stdlib```.

```C
#include <stdlib>
P = malloc(sizeof(int));
// Memoria suficiente para un entero
```


```mermaid
flowchart TB
subgraph Memoria
subgraph Stack
subgraph P
Dirección[3F5000AC o NULL]
end
end
subgraph Heap
subgraph Variable[int = *P]
Contenido[________]
end
end
end
Dirección --> Variable
```

<warning>
En caso de no existir memoria suficiente disponible al puntero <code>P</code> se le asigna valor <b>NULL</b>
</warning>

#### Destrucción de una variable dinámica

Para liberar la memoria de la variable dinámica se utiliza ```free``` definido en el archivo de cabecera ```stdlib```.

Se marcará la variable a la que apunta el puntero como liberada, aunque **la información no es destruida**, ya no es accesible.

```C
#include <stdlib>
free(P);
```
```mermaid
flowchart TB
subgraph Memoria
subgraph Stack
subgraph P
Dirección[3F5000AC o NULL]
end
end
subgraph Heap
subgraph Variable[Memoria liberada]
Contenido[________]
end
end
end
Dirección --X--> Variable
```

#### Acceso a una variable dinámica

```C
// Declaración
int i;
int* p;

// Creación
/* - - - */
p = malloc(sizeof(int))

// Escritura
i = 5;
*p = 5;

// Lectura
j = i;
j = *p;
```

## Asignación y comparación de punteros

#### Asignación de valores a punteros

```C
// Tenemos dos variables dinámicas P y Q
P = NULL; // Puntero a valor nulo
P = malloc(sizeof(int)); // Se reserva la memoria (se le asigna dirección de memoria)
*P = 3; // Se le asigna un entero
// Q tenía un valor previo *Q = 4;
P = Q; // Asignamos al puntero el valor de otro puntero
*P = 11;
printf("%d",*Q); // Resultado: 11
```
Es decir ahora ```P``` **no** tiene la dirección de memoria que se le asignó al liberar la memoria, **tiene la de ```Q```**. Visualmente:
```mermaid
flowchart LR
subgraph Stack
P
Q
end
subgraph Heap
11
end
Q --> 11
```

```mermaid
flowchart LR
subgraph Stack
P
Q
end
subgraph Heap
__
11
end
P --> __
Q --> 11
```

```mermaid
flowchart LR
subgraph Stack
P
Q
end
subgraph Heap
3
4
end
P --> 3
Q --> 4
```

```mermaid
flowchart LR
subgraph Stack
P
Q
end
subgraph Heap
3
4
end
P --> 4
Q --> 4
```

```mermaid
flowchart LR
subgraph Stack
P
Q
end
subgraph Heap
3
11
end
P --> 11
Q --> 11
```

### Comparación de punteros

```C
// Identidad
printf(P == Q); // Solo si tienen la misma dirección de memoria
// Igualdad
printf(*P == *Q); // Solo si su contenido es el mismo
```
```mermaid
---
title: Identidad
---
flowchart LR
subgraph P
dirP[3F5000AC]
end
subgraph Q
dirQ[3F5000AC]
end
subgraph valor[*P *Q]
11
end
dirP & dirQ --> valor
```

```mermaid
---
title: Igualdad
---
flowchart LR
subgraph P
dirP[3F5000AC]
end
subgraph Q
dirQ[600A232B]
end
subgraph valorP[*P]
vP[11]
end
subgraph valorQ[*Q]
vQ[11]
end
dirP --> valorP
dirQ --> valorQ
```


## Resumen sobre el uso de punteros y variables dinámicas

<deflist>
<def title="Definición y declaración">
<code-block lang="C">
typedef int* pEntero;
pEntero p;
</code-block>
</def>
<def title="Inicialización / Creación">
<code-block lang="C">
p = NULL;
// O para las Variables dinámica
p = malloc(sizeof(int));
</code-block>
<p>Se recomienda inicializar siempre los punteros, para no dejar valores <i>basura</i>.</p>
</def>
<def title="Destrucción de una variable">
<code-block lang="C">
free(p);
p = NULL;
</code-block>
<p>Siempre se debe hacer para crear un programa más eficiente en memoria.</p>
</def>
<def title="Contenido de la variable dinámica">
<code-block lang="C">
*p = valor; // Cambiar el valor
variable = *p; // Copiar el valor
</code-block>
</def>
<def title="Asignación de valores a punteros">
<code-block lang="C">
p = NULL; // Dirección nula
p = malloc(sizeof()); // Dirección de memoria recién liberada
p = q; // Dirección de otro puntero
</code-block>
</def>
<def title="Comparación de punteros">
<code-block lang="C">
p == q; p != q; // Comparación entre punteros
p == NULL; p != NULL; // Comparación con valor nulo
</code-block>
</def>
</deflist>
1 change: 1 addition & 0 deletions docs/topics/Teoria.topic
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ SPDX-License-Identifier: CC-BY-NC-4.0
<secondary>
<title>Programación II</title>
<!-- TODO Añadir Apuntes de Pro II -->
<a href="Tema-2.md" type="network" summary="Punteros en profundidad, las variables dinámicas, direcciones de memoria y la gestión de la memoria (pila (stack) y montículo (heap))."/>
<a href="Pro2324.topic" type="lock" summary="Proximamente...">Proximamente...</a>
</secondary>

Expand Down

0 comments on commit 3270330

Please sign in to comment.