usize vs u32 en Rust: cuál es la diferencia y qué elegir

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

usize vs u32: duelo de tipos enteros en Rust



Si llevas al menos una semana programando en Rust, seguro te has encontrado con esta situación: el compilador se queja porque intentas usar u32 para indexar un vector, y él requiere usize. O al revés: pasas un usize a una función que espera u32 y obtienes una ola roja en el IDE.



En Stack Overflow, la pregunta «What's the difference between usize and u32?» ha acumulado miles de visitas. No es casualidad: la confusión entre estos tipos es una de las trampas más comunes para los principiantes en Rust.



Aclaremos de una vez por todas en qué se diferencian, cuándo usar cada uno y cómo no meter la pata. ¡Allá vamos!



En resumen: la diferencia principal



usize es un entero sin signo cuyo tamaño depende de la arquitectura del sistema. En un sistema de 64 bits ocupa 8 bytes, en uno de 32 bits, 4 bytes. u32 siempre ocupa 4 bytes, independientemente de la plataforma.



Pero la diferencia no es solo el tamaño. Lo principal es la semántica:



  • usize — para tamaños, índices y cantidad de elementos en colecciones
  • u32 — para datos numéricos que no superen los 4 mil millones


Y sí, el compilador no permite mezclarlos sin una conversión explícita. No es un error, es una característica: así Rust te protege de errores relacionados con el ancho de bits de la arquitectura.



¿Por qué existe usize?



Imagina que escribes código que debe funcionar tanto en un viejo microcontrolador de 32 bits como en un servidor moderno de 64 bits. La longitud de un vector en un sistema de 32 bits no puede superar 2^32 - 1 elementos, mientras que en uno de 64 bits es 2^64 - 1.



Si usaras u32 para indexar en un sistema de 64 bits, simplemente no podrías acceder a elementos más allá de los 4 mil millones, aunque hubiera memoria suficiente. usize resuelve este problema: siempre puede contener el tamaño máximo de memoria posible en la arquitectura actual.



// Ejemplo: usize se adapta automáticamente a la arquitecturafn main() {    let large_vec: Vec<u8> = vec![0; 1_000_000_000]; // 1 mil millones de elementos        // usize puede contener este índice en cualquier plataforma    let index: usize = 999_999_999;    println!("Elemento: {}", large_vec[index]);        // En cambio, u32 podría no ser suficiente en un sistema de 32 bits    // let bad_index: u32 = 999_999_999; // En un sistema de 32 bits esto compilaría, pero...    // large_vec[bad_index as usize]; // ...habría que hacer la conversión}


Comparación en tabla



Característica usize u32
Tamaño en 64 bits 8 bytes 4 bytes
Tamaño en 32 bits 4 bytes 4 bytes
Rango (64 bits) 0 .. 2^64-1 0 .. 2^32-1
Propósito principal Índices, tamaños, longitudes Datos numéricos
Conversión implícita No No


¿Cuándo usar usize?



Siempre para indexar colecciones. Esta regla prácticamente no tiene excepciones. Si escribes vec[i] donde i es un u32, el compilador te dirá: «Oye, amigo, mejor usa usize».



// Correcto: usamos usize para índicesfn get_element(vec: &[i32], index: usize) -> Option<&i32> {    vec.get(index)}

// Incorrecto: u32 para indexar — habrá que convertirfn get_ele

Blogs

Book Recommendations