一篇学会 Rust 内存布局
创始人
2025-07-07 13:32:06
0

图片图片

题图忘了来自哪里..

整型,浮点型,struct,vec!,enum

本文是对 Rust内存布局[1] 的学习与记录

struct A {
    a: i64,
    b: u64,
}

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

struct C {
    a: i64,
    b: u64,
    c: i32,
}

struct D {
    a: i32,
    b: u64,
    c: i32,
    d: u64,
}

fn main() {
    println!("i32类型占的内存空间为:{}字节", std::mem::size_of::());
    println!("i64类型占的内存空间为:{}字节", std::mem::size_of::());
    println!(
        "[i64;4]占的内存空间为:{}字节",
        std::mem::size_of::<[i64; 4]>()
    );

    println!("结构体A占的内存空间为:{}字节", std::mem::size_of::());
    println!("结构体B占的内存空间为:{}字节", std::mem::size_of::());
    println!("结构体C占的内存空间为:{}字节", std::mem::size_of::());
    println!("结构体D占的内存空间为:{}字节", std::mem::size_of::());
}

输出

i32类型占的内存空间为:4字节
i64类型占的内存空间为:8字节
[i64;4]占的内存空间为:32字节
结构体A占的内存空间为:16字节
结构体B占的内存空间为:16字节
结构体C占的内存空间为:24字节
结构体D占的内存空间为:24字节

没啥好说的,和Go一样,struct会存在内存对齐/内存填充(8字节对齐)

D是因为编译器会优化内存布局,字段顺序重排

Rust中的Vec!和Go中的slice差不多,都是占24Byte,三个字段

struct SimpleVec {
    len: usize,      // 8
    capacity: usize, //8
    data: *mut T,    //8
}

fn main() {
    println!(
        "Vec!类型占的内存空间为:{}字节",
        std::mem::size_of::>()
    );

    println!(
        "Option类型占的内存空间为:{}字节",
        std::mem::size_of::>()
    );
}
Vec!类型占的内存空间为:24字节
Option类型占的内存空间为:16字节

但是对于enum类型,

会有一个tag字段,uint64,来标记变体,是None值还是Some值

struct Option {
    uint64 tag; // 占8字节 Some None
    i64; //实际存放的数据
}

struct SimpleVec {
    len: usize,      // 8
    capacity: usize, //8
    data: *mut T,    //8
}

enum Data {
    // tag,uint64,8字节
    I32(i32),             //  4字节,但需内存对齐到8字节?
    F64(f64),             // 8字节
    Bytes(SimpleVec), // 24字节
}

fn main() {
    println!(
        "Data这个Enum类型占的内存空间为:{}字节",
        std::mem::size_of::()
    );
}

输出为:

Data这个Enum类型占的内存空间为:32字节

Rust的enum类似C++ std::variant的实现(大致是用union实现的)

union的内存大小是其成员中最大的那个成员的大小,

类似的,对于Data这个Enum类型,会选择最大的那个成员的大小

所以24+tag的8字节,最终为32字节 (tag在这里就用来标识其为i32,还是f64,或者是Vec)

嵌套的枚举:

struct SimpleVec {
    len: usize,      // 8
    capacity: usize, //8
    data: *mut T,    //8
}

enum Data {
    // tag,uint64,8字节
    I32(i32),             //  4字节,但需内存对齐到8字节?
    F64(f64),             // 8字节
    Bytes(SimpleVec), // 24字节
}

type OptData = Option;

fn main() {
    println!(
        "OptData这个Option类型占的内存空间为:{}字节",
        std::mem::size_of::()
    );
}

输出:

OptData这个Option类型占的内存空间为:32字节

因为编译器会对嵌套的枚举类型进行优化,会将其tag展开, 把多个tag合在一起了,类似下面:

展开变成一个枚举(None是uint64,能标识非常多信息)

type OptData = Option;

enum Option {
    Some,
    None,
}

enum OptData_ {
    I32(i32);
    F64(f64);
    Bytes(SimpleVec),
    None
}

元组tuple

rust中的元组大小固定吗?

在Rust中,元组的大小是固定的。这里解释一下元组大小固定的含义:

举个例子:

let tuple = (1, 2.0, "three");

这里元组包含一个i32,一个f64和一个字符串。编译器会预先知道:

这20字节的内存在编译时就已分配,运行期不会改变。

如果后续试图给这个元组添加或减少元素,编译都会报错。

所以说,元组的大小和内容是固定的,这是Rust实现方式的一部分。

更多可参考Rust 数据内存布局[2]

参考资料

[1]Rust内存布局: https://www.bilibili.com/video/BV1Bm4y1c71r

[2]Rust 数据内存布局: https://blog.csdn.net/techdashen/article/details/120257323

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...