> ## Documentation Index
> Fetch the complete documentation index at: https://apuntes.simulab.es/llms.txt
> Use this file to discover all available pages before exploring further.

# Memoria y punteros en C: pila, montón, paso por referencia y malloc

> Punteros en C explicados línea a línea: direcciones, operadores & y *, paso por valor y por referencia, aritmética de punteros, la pila y el montón, malloc y free, y errores típicos.

<Card title="Abrir el simulador" icon="flask" href="https://simulab.es/programacion/punteros">
  Programas en C línea a línea con la pila, el montón y a dónde apunta cada puntero.
</Card>

Los punteros son la parte de C que más cuesta al principio, y la que más errores provoca. La razón es que no se ven: viven en la memoria. Este simulador ejecuta programas cortos **línea a línea** y dibuja la **pila** y el **montón**, para que se vea qué pasa realmente al pasar un argumento, recorrer un vector o pedir memoria con `malloc`.

## Lo que vas a aprender

* Qué es una dirección de memoria y un puntero.
* Los operadores `&` y `*`.
* La diferencia entre paso por valor y por referencia.
* La aritmética de punteros y su relación con los vectores.
* Cómo funcionan la pila y el montón, `malloc` y `free`.

## Cómo se usa el simulador

* Elige un programa: **paso por valor**, **paso por referencia**, **aritmética de punteros**, **vector dinámico** o **matriz dinámica**.
* Avanza con **⏮**, **◀**, **▶ Ejecutar**, **▶** y **⏭**, o arrastra el deslizador.
* Se ven el **código** con la línea actual, la **pila** con un marco por función, el **montón** y la **salida** del programa.
* Lo que acaba de cambiar se resalta. **Pasa el ratón** (o toca) un puntero para ver a qué apunta.

## Fundamentos teóricos

### Direcciones y punteros

Cada variable ocupa un lugar en la memoria con una **dirección**. Un **puntero** es una variable que guarda una dirección.

```c theme={null}
int x = 10;
int *p = &x;   // p guarda la dirección de x
*p = 20;       // escribe en x a través de p: ahora x vale 20
```

* `&x`: la dirección de `x`.
* `*p`: la variable a la que apunta `p` (desreferenciar).
* En una declaración, `int *p` significa "p es un puntero a int".

### Paso por valor y por referencia

En C los argumentos se pasan **por valor**: la función recibe una **copia**.

```c theme={null}
void cambia(int n, int m)   { int aux = m; m = n; n = aux; }   // no funciona
void cambia(int *n, int *m) { int aux = *m; *m = *n; *n = aux; } // sí
```

Para que una función modifique variables de quien la llama, hay que pasarle sus **direcciones**: `cambia(&n, &m)`.

### Aritmética de punteros

Sumar 1 a un puntero avanza **un elemento**, no un byte: `p + 1` avanza `sizeof(*p)` bytes (4 en un `int` típico). Por eso:

$$
v[i] \equiv *(v + i)
$$

El nombre de un vector se comporta como un puntero a su primer elemento.

### La pila

Guarda las **variables locales**. Cada llamada a una función crea un **marco** encima; al terminar, se destruye. Por eso nunca hay que devolver la dirección de una variable local.

### El montón (heap)

Memoria que se pide en tiempo de ejecución y **sigue existiendo** hasta que se libera:

```c theme={null}
int *v = malloc(n * sizeof(int));
if (v == NULL) { /* no hay memoria */ }
/* ... usar v[0] .. v[n-1] ... */
free(v);
v = NULL;
```

## Ejemplos resueltos

<AccordionGroup>
  <Accordion title="Ejemplo 1 · ¿Por qué no intercambia?" defaultOpen>
    `cambia(n, m)` intercambia sus **copias**, que desaparecen al volver a `main`. `cambia(&n, &m)` recibe las direcciones y, con `*n` y `*m`, escribe en las variables de `main`.
  </Accordion>

  <Accordion title="Ejemplo 2 · Aritmética">
    Con `int v[] = {10, 20, 30}; int *p = v;`: `*(p + 2)` vale 30. Si `p` está en la dirección 1000, `p + 2` está en 1008.
  </Accordion>

  <Accordion title="Ejemplo 3 · Matriz dinámica">
    Una matriz de `f × c` se puede pedir como un vector de `f` punteros, cada uno con su fila de `c` enteros. Se libera al revés: primero cada fila y luego el vector de punteros.
  </Accordion>
</AccordionGroup>

## Experimenta con el simulador

<Steps>
  <Step title="Valor y referencia">
    Ejecuta los dos programas de intercambio y compara los marcos de la pila.
  </Step>

  <Step title="Aritmética">
    En el programa de aritmética, mira cuánto cambia la dirección del puntero en cada `p++`.
  </Step>

  <Step title="Montón">
    En el vector dinámico, observa qué queda en el montón cuando termina la función que hizo el `malloc`.
  </Step>
</Steps>

## Errores frecuentes

* **Usar un puntero sin inicializar** (apunta a cualquier sitio).
* **Desreferenciar NULL.**
* **Olvidar el `free`** (fuga de memoria) o hacerlo dos veces.
* **Usar memoria después del `free`** (puntero colgante).
* **Devolver la dirección de una variable local.**
* **Olvidar `sizeof`** en el `malloc`.

## Herramientas relacionadas

<CardGroup cols={3}>
  <Card title="Recursión en C" icon="arrows-rotate" href="/programacion/c/recursion">
    La pila de llamadas.
  </Card>

  <Card title="ArrayList y lista enlazada" icon="list" href="/programacion/java/listas">
    Nodos enlazados con referencias.
  </Card>

  <Card title="Conversor de bases" icon="calculator" href="/electronica/sistemas-numeracion/conversor-bases">
    Direcciones en hexadecimal.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.