Skip to content

Instantly share code, notes, and snippets.

@gusdelact
Created December 13, 2025 08:03
Show Gist options
  • Select an option

  • Save gusdelact/9a7e4e0ebca88970377a33854b6700a4 to your computer and use it in GitHub Desktop.

Select an option

Save gusdelact/9a7e4e0ebca88970377a33854b6700a4 to your computer and use it in GitHub Desktop.
// ------------------------------------------------------------
// Ejemplo didáctico: referencias mutables, structs, arrays,
// swap y un árbol binario con Box + Option (estilo C → Rust).
// ------------------------------------------------------------
#[derive(Debug)]
struct A {
c1: u8,
c2: u8,
}
/// f1: recibe una referencia mutable a un u8.
/// - Lee el valor actual (desreferenciando) y lo copia en `x`.
/// - Incrementa `x` (solo la copia local).
/// - Incrementa el valor original a través de la referencia.
/// - Regresa `x` (que es independiente del valor final en memoria).
fn f1(p0: &mut u8) -> u8 {
// Copiamos el valor apuntado por p0 (u8 es Copy, así que se copia barato)
let mut x = *p0;
// Incrementamos la copia local
x = x + 1;
// Modificamos el valor original (el que vive fuera de la función)
*p0 = *p0 + 1;
// Regresamos la copia local incrementada
x
}
/// f2: recibe una referencia mutable a una estructura A.
/// - Modifica sus campos in-place.
/// - Imprime el contenido y la dirección donde vive la estructura.
fn f2(p1: &mut A) {
// Acceso directo a campos vía la referencia mutable
p1.c1 = p1.c1 + 1;
p1.c2 = p1.c2 + 1;
// Debug: imprime el estado actual de la estructura
println!("{:?}", p1);
// Imprime la dirección (puntero) donde vive el objeto apuntado por p1
println!("{:p}", p1);
}
/// f3: demuestra el uso de una referencia mutable "re-asignable"
/// (similar al uso de un puntero en C, pero con reglas seguras).
fn f3() {
let mut x: u8 = 1;
let mut y: u8 = 2;
// Arreglo fijo de 10 bytes, inicializado a 0
let mut z: [u8; 10] = [0; 10];
// Referencia mutable a u8 (nota: NO puede ser null)
let mut ip: &mut u8;
// ip apunta a x
ip = &mut x;
// y toma el valor apuntado por ip (o sea, el valor de x)
y = *ip;
// cambiamos x a través de ip
*ip = 0;
// ahora ip apunta al primer elemento del arreglo z
ip = &mut z[0];
// incrementamos el primer elemento (0 + 10)
*ip = *ip + 10;
// y toma el valor de z[0] + 1
y = *ip + 1;
// incrementamos z[0] con el operador compuesto
*ip += 1;
// Mostramos el arreglo completo
println!("{:?}", z);
// y se usa solo para evitar warnings en algunos compiladores/configs
let _ = y;
}
/// swap: intercambio clásico, estilo C, usando referencias mutables.
/// - Equivalente conceptual a swap(&mut a, &mut b).
fn swap(px: &mut i8, py: &mut i8) {
// temp guarda una copia del valor apuntado por px
let temp: i8 = *px;
// px toma el valor de py
*px = *py;
// py toma el valor original de px (guardado en temp)
*py = temp;
}
/// f4: demuestra cómo modelar un árbol binario de forma idiomática en Rust:
/// - `Box<TNode>`: el hijo vive en el heap.
/// - `Option<Box<TNode>>`: reemplaza el clásico NULL.
fn f4() {
// Struct local a la función (solo visible dentro de f4)
#[derive(Debug)]
struct TNode {
word: String,
count: i32,
left: Option<Box<TNode>>,
right: Option<Box<TNode>>,
}
// Nodo hoja simple (sin hijos)
let _node1 = TNode {
word: "hello".to_string(),
count: 1,
left: None,
right: None,
};
// Nodo con hijo izquierdo
let _node2 = TNode {
word: "root".to_string(),
count: 1,
left: Some(Box::new(TNode {
word: "left".to_string(),
count: 1,
left: None,
right: None,
})),
right: None,
};
// Creamos un nodo en el heap (Box) para poder "poseerlo" desde otro nodo
let first = Box::new(TNode {
word: "first".to_string(),
count: 1,
left: None,
right: None,
});
// second toma ownership de `first` en su campo right.
// Importante: después de esto, ya NO puedes usar la variable `first`.
let _second = TNode {
word: "second".to_string(),
count: 1,
left: None,
right: Some(first),
};
// _second vive hasta el final de f4; al salir, se libera todo automáticamente.
}
fn main() {
// ------------------------------------------------------------
// 1) Prueba con u8 y paso por referencia mutable (f1)
// ------------------------------------------------------------
let mut a: u8 = 0x32; // 50 en decimal
println!("{:?}", a);
a = 0x64; // 100 en decimal
println!("{:?}", a);
// f1 modifica `a` vía &mut, y regresa un valor (que aquí ignoramos)
let _ret = f1(&mut a);
// a ya fue incrementado dentro de f1
println!("{:?}", a);
a = 0x74; // 116 en decimal
println!("{:?}", a);
// ------------------------------------------------------------
// 2) Prueba con struct A y paso por referencia mutable (f2)
// ------------------------------------------------------------
let mut b = A { c1: 2, c2: 3 };
// Estado antes
println!("{:?}", b);
println!("{:p}", &b); // dirección de b en main
// f2 modifica b in-place
f2(&mut b);
// Estado después
println!("{:?}", b);
println!("{:p}", &b); // debe ser la misma dirección
// ------------------------------------------------------------
// 3) Prueba con referencias mutables re-asignables (f3)
// ------------------------------------------------------------
f3();
// ------------------------------------------------------------
// 4) swap clásico con referencias mutables
// ------------------------------------------------------------
let mut c: i8 = 1;
let mut d: i8 = 2;
swap(&mut c, &mut d);
println!("{:?}", c); // 2
println!("{:?}", d); // 1
// ------------------------------------------------------------
// 5) Árbol binario con Box + Option (f4)
// ------------------------------------------------------------
f4();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment