usize vs u32 em Rust: qual a diferença e o que escolher

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

usize vs u32: duelo de tipos inteiros em Rust



Se você programa em Rust há pelo menos uma semana, com certeza já passou por esta situação: o compilador reclama porque você está tentando usar u32 para indexar um vetor, e ele exige usize. Ou o contrário — você passa usize para uma função que espera u32 e recebe uma onda vermelha na IDE.



No Stack Overflow, a pergunta «What's the difference between usize and u32?» já teve milhares de visualizações. Não é por acaso — a confusão entre esses tipos é uma das armadilhas mais comuns para iniciantes em Rust.



Vamos entender de uma vez por todas como eles diferem, quando usar cada um e como não cometer erros. Vamos lá!



Resumindo: a principal diferença



usize é um inteiro sem sinal cujo tamanho depende da arquitetura do sistema. Em um sistema de 64 bits, são 8 bytes; em um de 32 bits, são 4 bytes. u32 tem sempre 4 bytes, independentemente da plataforma.



Mas a diferença não é apenas no tamanho. O principal é a semântica:



  • usize — para tamanhos, índices e quantidade de elementos em coleções
  • u32 — para dados numéricos que não ultrapassem 4 bilhões


E sim, o compilador não permite misturá-los sem uma conversão explícita. Isso não é um bug, é uma funcionalidade — assim o Rust protege você de erros relacionados à largura da arquitetura.



Por que usize existe?



Imagine que você está escrevendo um código que deve funcionar tanto em um microcontrolador antigo de 32 bits quanto em um servidor moderno de 64 bits. O comprimento de um vetor em um sistema de 32 bits não pode exceder 2^32 - 1 elementos, enquanto em um de 64 bits pode chegar a 2^64 - 1.



Se você usasse u32 para indexação em um sistema de 64 bits, simplesmente não conseguiria acessar elementos além de 4 bilhões — mesmo que houvesse memória suficiente. usize resolve esse problema: ele sempre comporta o tamanho máximo de memória possível na arquitetura atual.



// Exemplo: usize se ajusta automaticamente à arquiteturafn main() {    let large_vec: Vec<u8> = vec![0; 1_000_000_000]; // 1 bilhão de elementos        // usize comporta esse índice em qualquer plataforma    let index: usize = 999_999_999;    println!("Elemento: {}", large_vec[index]);        // Já u32 pode ser insuficiente em um sistema de 32 bits    // let bad_index: u32 = 999_999_999; // Em um sistema de 32 bits, isso compilaria, mas...    // large_vec[bad_index as usize]; // ...seria necessário fazer a conversão}


Comparação em tabela



Característica usize u32
Tamanho em 64-bit 8 bytes 4 bytes
Tamanho em 32-bit 4 bytes 4 bytes
Faixa (64-bit) 0 .. 2^64-1 0 .. 2^32-1
Finalidade principal Índices, tamanhos, comprimentos Dados numéricos
Conversão implícita Não Não


Quando usar usize?



Sempre para indexação de coleções. Esta é uma regra praticamente sem exceções. Se você escrever vec[i], onde i é um u32, o compilador dirá: "Ei, amigo, use usize".



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

// Incorreto: u32 para indexação — será necessário converterfn get_ele

Blogs

Book Recommendations