rust字节数组

array和slice的概念

数组(array)是一组拥有相同类型 T 的对象的集合,在内存中是连续存储的。数组使用中括号 [] 来创建,且它们的大小在编译时会被确定。数组的类型标记为 [T; length]T 为元素类型,length 表示数组大小)。

切片(slice)类型和数组类似,但其大小在编译时是不确定的。相反,切片是一个双字对象(two-word object),第一个字是一个指向数据的指针,第二个字是切片的长度。这个 “字” 的宽度和 usize 相同,由处理器架构决定,比如在 x86-64 平台上就是 64 位。slice 可以用来借用数组的一部分。slice 的类型标记为 &[T]

字节数组的几种类型:

(一)      [u8; N](固定大小的字节数组)
这是一个固定长度的数组,长度 N 在编译时确定。
存储在栈上(stack),如果数组过大可能导致栈溢出。
拥有数据的所有权。
大小无法在运行时改变, 如果需要改变,只能释放了再新建。
访问时可以使用 & 获取切片(&[u8])

(二)   &[u8](字节切片 引用)
动态大小,存储在堆上或栈上,通常是借用(reference)。
可通过 as_ref()、deref() 或 slice::from_ref() 从数组转换。
它是一个对字节序列的不可变引用,可以指向[u8; N] 或Vec<u8> 等的一部分
不拥有数据,仅借用;长度在运行时确定。

切片本身 不拥有 任何数据。它只是指向已存在字节数据的指针和长度。数据的所有权属于切片所引用的原始数据。
切片的大小在运行时确定,由其指向的数据的长度决定。

(三)   &mut [u8](可变字节切片)
和 &[u8] 类似,但允许修改数据

(四)   Vec(动态字节数组)
可变长,存储在堆上(heap)。
适用于需要增长或缩短的字节数据
拥有数据的所有权,可以动态调整大小
允许 push、resize、extend 等操作。
通过 push, pop, insert, remove 等方法进行增删元素

(五)  Box<[u8]>(堆分配的字节数组)
固定长度的堆分配数组,与 Vec 类似但不可变长。
适用于数据不需要增长的情况,但仍希望存储在堆上。
let boxed: Box<[u8]> = vec![1, 2, 3, 4].into_boxed_slice();
拥有所有权,在堆上分配,大小固定但可以在运行时创建

(六)   Cow<[u8]>(惰性克隆的字节数组)
Cow(Copy on Write,写时复制)适用于既可能是借用的(&[u8])也可能是拥有的(Vec)数据。
适用于优化性能,避免不必要的复制,只有在需要修改时才会克隆数据。

(七) [u8] 未定大小的字节切片
这是一个抽象的字节切片类型,通常在泛型或 trait 定义中使用。
无法直接实例化,仅作为类型参数出现。
是一个视图(view)而非拥有数据的类型

(八) String和&str
用于文本字符串,以UTF-8编码的字节。本质上也是字节序列。
String拥有数据, &str是一个切片引用。

在某些情况下,你可能会将 String 或 &str 视为字节数组来处理,例如在处理 ASCII 文本或进行底层字符串操作时。但要注意,它们强制 UTF-8 编码,可能不适合处理任意二进制数据。

转换:
[u8; N] 可以转换为 &[u8] 或 &mut [u8](用 &符号 借用)
&[u8] 可以转换为 Vec( 用.to_vec()复制为Vec<u8>)
Vec 可以转换为 Box<[u8]>(比如上面的介绍的into_boxed_slice())
&[u8] 或 Vec 可以转换为 Cow<[u8]>
Vec<u8> 可以通过 .as_slice() 转为 &[u8]
&[u8] 转化 &[u8; N] , 用 try_into()

注意事项:
&[u8] 和 Box<[u8]> 是不可变的(除非使用内部可变性如 Cell 或 RefCell)
&[u8] 和 &mut [u8] 长度由引用的数据决定

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注