先说下我的理解,如果有误感谢大佬们指出:
-
[T; N]类似于数组的概念,长度在编译期可知,且不会变化,长度N也是类型的一部分。[T; N]满足Sized trait
-
[T]和[T; N]的区别在于[T]的长度在编译期不可知,不满足Sized trait。因此一般都使用&[T]来指向[T],这个指针除了有数据的地址,还保存有[T]的长度信息,因此被称为胖指针fat pointer
现在有这样一段代码
fn main() {
let array: [u8; 5] = [1, 2, 3, 4, 5];
let slice: &[u8] = &array[..];
println!("Array pointer size {}", size_of_val(&&array)); // 8
println!("Slice pointer size {}", size_of_val(&slice)); // 16
println!("Array length {}", array.len()); // 5
println!("Slice length {}", slice.len()); // 5
}
Array的指针大小是8 bytes,Slice则是16 bytes,似乎正好满足Slice是fat pointer的事实。
接下来问题来了,发现array.len()和slice.len()都调用的是下面的代码
impl<T> [T] {
pub const fn len(&self) -> usize {
ptr::metadata(self)
}
}
array和slice都是从自己的指针中取metadata,那么两个都是胖指针?那为什么打印Array指针大小为8而不是16呢?
还是说我计算Array指针大小的写法是错误的?
求大佬们解答一下,谢谢~
1
共 3 条评论, 1 页
评论区
写评论感谢感谢😀,没人教的话我怎么也不会想到是这个原因
--
👇
aj3n: https://doc.rust-lang.org/stable/reference/type-coercions.html#unsized-coercions
你关于指针长度的理解没有问题. 两种写法都调用的<[T]>::len主要是因为调用array.len()的时候发生了
unsized-coercion
, 会把&[T;N]隐式转换成&[T], 参考上面的链接; 我感觉这个不是很重要标准库实现技巧,以后对关注到类似的隐式转换简单参考下就好;个人理解
array
是相当于下面一个C语言结构体数据&array
相当于下面一个C语言结构体数据:&&array
相当于下面一个C语言ArrayRef
的指针:&&array=&ArrayRef所以
size_of_val(&&array)
是返回当前平台存储的指针大小,size_of_val(&array)
返回ArrayRef
结构体大小https://doc.rust-lang.org/stable/reference/type-coercions.html#unsized-coercions
你关于指针长度的理解没有问题. 两种写法都调用的<[T]>::len主要是因为调用array.len()的时候发生了
unsized-coercion
, 会把&[T;N]隐式转换成&[T], 参考上面的链接; 我感觉这个不是很重要标准库实现技巧,以后对关注到类似的隐式转换简单参考下就好;