Rust 程式設計:記憶體佈局

linghuyichong發表於2020-03-16

1、每種型別都有一個資料對齊屬性。在X86平臺上u64和f64都是按照32位對齊的。

2、一種型別的大小是它對齊屬性的整數倍,這保證了這種型別的值在陣列中的偏移量都是其型別尺寸的整數倍,可以按照偏移量進行索引。需要注意的是,動態尺寸型別的大小和對齊可能無法靜態獲取。

3、結構體的對齊屬性等於它所有成員的對齊屬性中最大的那個。Rust會在必要的位置填充空白資料,以保證每一個成員都正確地對齊,同時整個型別的尺寸是對齊屬性的整數倍。

例子:

struct  A { 
    a: u8, 
    b: u32, 
    c:u16, 
}

會填充為:

struct  A { 
    a: u8, 
    _pad1: [u8; 3], // 為了對齊b 
    b: u32, 
    c: u16, 
    _pad2: [u8; 2], // 保證整體型別尺寸是4的倍數 
}

4、注意點,兩個同樣型別的複合型別其分佈規則並不一定一塵不變。例子:

struct  A { 
    a: i32, 
    b: u64, 
} 
struct  B { 
    a: i32, 
    b: u64, 
}

Rust中不保證A的例項和B的例項有同樣的資料填充和成員順序。

原因:Rust編譯器會進行最佳化。如下:

struct  Foo<T, U> { 
    count: u16, 
    data1: T, 
    data2: U, 
}

對於上面的泛型結構體,Foo<u32, u16>和Foo<u16, u32>按照記憶體最佳化的原則要求兩者順序不一樣。

5、求解結構體的大小
使用std::mem,有兩種方法,分佈是size_of_val和size_of,例子如下:

use std::mem;
struct A {
    a: u8,
    b: u16,
}

fn main() {
    let aa = A {a: 1, b:2};
    println!("size = {}", mem::size_of_val(&aa));
    println!("size = {}", mem::size_of::<A>());
    println!("Hello, world!");
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章