pointers - 接受字符串引用的函数参数是否直接指向字符串变量或 Rust 堆上的数据
问题描述
我从The Rust Book中拍摄了这张照片和代码。
为什么s
指向s1
而不只是堆本身的数据?
如果是这样,它是如何工作的?怎么s
点到s1
。它是否分配了带有 ptr 字段的内存,该字段包含s1
. 然后,doess1
又指向数据。
在s1
中,我似乎正在查看一个带有指针、长度和容量的变量。只有ptr
字段是这里的实际指针吗?
这是我的第一个系统级语言,所以我认为与 C/C++ 的比较不会帮助我理解这一点。我认为部分问题在于我不太了解指针到底是什么以及操作系统如何分配/取消分配内存。
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
解决方案
- 内存只是一个巨大的数组,可以通过任何偏移量(例如 )来索引
u64
。 - 这个偏移量称为地址,
- 和一个存储地址的变量,称为指针。
- 但是,通常只分配一小部分内存,因此并非每个地址都是有意义的(或有效的)。
- 分配是对程序有意义的(顺序)地址范围的请求(因此它可以访问/修改)。
- 每个对象(我指的是任何类型的对象)都位于分配的内存中(因为未分配的内存对程序毫无意义)。
- 引用实际上是一个指针,它(由编译器)保证是有效的(即从编译器已知的某个对象的地址派生)。也看看std doc。
这里是这些概念的一个例子(操场):
// This is, in real program, implicitly defined,
// but for the sake of example made explicit.
// If you want to play around with the example,
// don't forget to replace `usize::max_value()`
// with a smaller value.
let memory = [uninitialized::<u8>(); usize::max_value()];
// Every value of `usize` type is valid address.
const SOME_ADDR: usize = 1234usize;
// Any address can be safely binded to a pointer,
// which *may* point to both valid and invalid memory.
let ptr: *const u8 = transmute(SOME_ADDR);
// You find an offset in our memory knowing an address
let other_ptr: *const u8 = memory.as_ptr().add(SOME_ADDR);
// Oversimplified allocation, in real-life OS gives a block of memory.
unsafe { *other_ptr = 15; }
// Now it's *meaningful* (i.e. there's no undefined behavior) to make a reference.
let refr: &u8 = unsafe { &*other_ptr };
我希望澄清大多数事情,但让我们明确地涵盖这些问题。
为什么
s
指向s1
而不只是堆本身的数据?
s
是一个引用(即有效指针),所以它指向s1
. 它可能(并且可能会)被编译器优化为与 相同的内存s1
,从逻辑上讲,它仍然是指向 的不同对象s1
。
怎么
s
点到s1
。它是否分配了一个ptr
包含内存地址的字段的内存s1
。
“指向”链仍然存在,因此s.len()
在内部调用转换为s.deref().len
,并访问转换为的字符串数组的某些字节s.deref().ptr.add(index).deref()
。
图片上显示了 3 个内存块:&s
、&s1
、s1.ptr
是不同的(除非优化)内存地址。所有这些都存储在分配的内存中。前两个实际上存储在称为堆栈的预分配(即在调用main
函数之前)内存中,通常它不称为已分配内存(尽管我在此答案中忽略了这种做法)。相反,指针指向由用户程序显式分配的内存(即在进入之后)。s1.ptr
main
在
s1
中,我似乎正在查看一个带有指针、长度和容量的变量。只有ptr
字段是这里的实际指针吗?
对,就是这样。长度和容量只是常见的无符号整数。
推荐阅读
- android - Android 开发部署到 Google 控制台失败
- swift - 使用 Core Data 从 Cloud Firestore 中提取数据后保存空数据模型
- java - 根据用户输入中出现的字符从包含字母的数组列表中删除字符
- python - 如何在 python 中的稀疏矩阵上应用 colamd 算法?
- react-native - React useEffect 引发“创建不是函数”错误
- java - 在 Optional 中包装数据类型导致的 ClassCastException
- kubernetes - Kubernetes:将本地文件夹挂载到 pod 时出现问题 - “0/1 个节点可用:1 个节点发生卷节点关联性冲突。”
- mongodb - 如何在一个聚合管道阶段进行计数并在稍后阶段使用它?
- asp.net - 如何从 Web API 获取数据到 Xamarin 表单选择器?
- javascript - Get Timer ID in Node.js