怪不得rust这么省内存,原来是有内存对齐

Rust是一门精心设计的语言,它的内存布局和分配尤其如此。和其他语言一样,rust也需要对内存进行对齐,下面我们学习下rust是如何做的吧。
Rust使用了与C语言相似的内存布局和对齐规则,以确保数据的访问和操作是有效和可靠的。

内存布局:
在Rust中,变量和数据结构在内存中被连续地存储。根据变量的类型和大小,它们可能会占用不同的字节数。Rust的内存布局通常遵循以下原则:

  • 栈(Stack): 栈是一种后进先出(LIFO)的数据结构,用于存储局部变量和函数调用的上下文信息。在Rust中,栈上的变量的大小必须在编译时确定,并且在变量超出作用域时会自动释放。
  • 堆(Heap): 堆是用于动态分配内存的区域,用于存储变量和数据结构。在Rust中,可以使用 Box 类型或 Vec 类型等动态分配的数据结构来在堆上分配内存。堆上的数据需要手动释放,通常使用 drop 函数或析构函数来执行清理操作。

对齐:
对齐是指在内存中如何排列数据的起始地址。对齐的目的是为了提高数据访问的效率和性能。在Rust中,对齐规则通常遵循以下原则:

  • 最大对齐: 变量和数据结构的对齐要求通常是其成员中最大对齐要求的倍数。例如,如果一个结构体中有一个 u32 类型的成员和一个 u8 类型的成员,那么结构体的对齐要求将是4( u32 的对齐要求)。
  • 对齐补齐: 如果一个结构体的对齐要求不是其成员中最大对齐要求的倍数,那么编译器将在成员之间插入填充字节来满足对齐要求。

下面通过几个例子来说明内存布局和对齐的概念:

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

在这个例子中,结构体 Example 包含了一个 u8 类型的成员 a ,一个 u32 类型的成员 b ,和一个 u16 类型的成员 c 。根据对齐规则,结构体的对齐要求将是4( u32 的对齐要求)。
所以,编译器将在成员 a 和成员 b 之间插入2个填充字节,以保证 b 的对齐要求。因此, Example 结构体的大小将是12个字节。

struct Point {
    x: f32,
    y: f32,
    z: f32,
}

在这个例子中,结构体 Point 包含了三个 f32 类型的成员 xyz 。根据对齐规则, f32 的对齐要求通常是4。
所以,编译器不需要插入填充字节,因为每个 f32 类型的成员都满足对齐要求。因此, Point 结构体的大小将是12个字节。
通过了解内存布局和对齐的原则,我们可以更好地理解Rust中变量和数据结构在内存中的存储方式,并编写出更高效和可靠的代码。

可以使用 std::mem 模块中的 size_ofalign_of 函数来获取类型的大小和对齐要求。例如, std::mem::size_of::<u32>() 将返回 4 ,表示 u32 类型占用4个字节。

size_of 函数:
用于获取给定类型的大小(以字节为单位)。它的语法如下:

std::mem::size_of::<T>()

其中, T 是要获取大小的类型。例如,要获取 u32 类型的大小,可以使用以下代码:

let size = std::mem::size_of::<u32>();
println!("Size of u32: {}", size);

align_of 函数:
用于获取给定类型的对齐要求(以字节为单位)。它的语法如下:

std::mem::align_of::<T>()

其中, T 是要获取对齐要求的类型。例如,要获取 u32 类型的对齐要求,可以使用以下代码:

let align = std::mem::align_of::<u32>();
println!("Alignment of u32: {}", align);

需要注意的是,Rust的内存布局和对齐规则可能会受到编译器、操作系统和目标平台的影响,因此具体的细节可能会有所不同。在编写涉及内存布局和对齐的代码时,建议使用标准库提供的函数和类型来确保正确性和可移植性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值