mem::size_of în Rust

Returnează câți octeți ocupă în memorie o valoare de tipul T (fără ce alocă eventual în heap).

Sintaxă
pub const fn size_of<T>() -> usize
pub fn size_of_val<T: ?Sized>(val: &T) -> usize

Ce face mem::size_of

mem::size_of::<T>() dă dimensiunea în octeți a unui tip, calculată la compilare. Pentru tipurile care au date în heap (String, Vec, Box) se numără doar partea de pe stivă: pointerul, lungimea și capacitatea, nu și conținutul. size_of_val(&x) funcționează și pentru tipuri fără dimensiune fixă, ca str sau slice-uri.

Rezultatele depind de platformă: pe un sistem de 64 de biți un usize sau un pointer are 8 octeți. Structurile pot avea octeți de umplutură (padding) pentru aliniere. Datorită unei optimizări, Option<Box<T>> și Option<&T> au aceeași dimensiune ca pointerul simplu.

Ce returnează

Dimensiunea în octeți, ca usize.

Exemple

Exemplul 1: Dimensiunile tipurilor obișnuite

Valorile sunt cele de pe un sistem de 64 de biți, unde au rulat exemplele.

use std::mem::size_of;

fn main() {
    println!("u8:            {}", size_of::<u8>());
    println!("i32:           {}", size_of::<i32>());
    println!("f64:           {}", size_of::<f64>());
    println!("char:          {}", size_of::<char>());
    println!("bool:          {}", size_of::<bool>());
    println!("usize:         {}", size_of::<usize>());
    println!("&str:          {}", size_of::<&str>());
    println!("String:        {}", size_of::<String>());
    println!("Vec<i32>:      {}", size_of::<Vec<i32>>());
    println!("Box<i32>:      {}", size_of::<Box<i32>>());
    println!("Option<Box>:   {}", size_of::<Option<Box<i32>>>());
    println!("Option<i32>:   {}", size_of::<Option<i32>>());
}

Rezultat

u8:            1
i32:           4
f64:           8
char:          4
bool:          1
usize:         8
&str:          16
String:        24
Vec<i32>:      24
Box<i32>:      8
Option<Box>:   8
Option<i32>:   8

Exemplul 2: Structuri, aliniere și size_of_val

Elev are 1 + 4 octeți de date, dar ocupă 8, din cauza alinierii lui u32. Pentru texte, size_of_val numără octeții UTF-8 (ă, ș ocupă câte 2).

use std::mem::{size_of, size_of_val};

struct Elev {
    _clasa: u8,
    _puncte: u32,
}

fn main() {
    println!("Elev: {} octeți", size_of::<Elev>());
    println!("(u8, u32): {} octeți", size_of::<(u8, u32)>());

    let text = "Brașov";
    println!("{text:?}: {} octeți, {} caractere", size_of_val(text), text.chars().count());

    let note = [9u8, 10, 8, 7];
    println!("tabloul de note: {} octeți", size_of_val(&note));
}

Rezultat

Elev: 8 octeți
(u8, u32): 8 octeți
"Brașov": 7 octeți, 6 caractere
tabloul de note: 4 octeți

Greșeli frecvente

  • Crezi că size_of::<String>() (24) este lungimea textului: este doar mărimea structurii de pe stivă. Lungimea textului este s.len().
  • Te bazezi pe ordinea câmpurilor sau pe dimensiunea unei structuri obișnuite: Rust poate reordona câmpurile. Pentru o așezare fixă (de exemplu pentru C), folosește #[repr(C)].

Comenzi înrudite

  • Box: Pune o valoare în memoria heap și o deține; folosit pentru tipuri recursive și pentru Box<dyn Trait>.
  • u8: Întreg fără semn pe 8 biți (0-255): tipul unui octet, folosit pentru date binare și text ASCII/UTF-8.
  • i32: Tipul implicit pentru numere întregi cu semn, pe 32 de biți: de la -2147483648 la 2147483647.