接受字符串引用的函数参数是否直接指向字符串变量或 Rust 中堆上的数据
Does a function parameter that accepts a string reference point directly to the string variable or the data on the heap in Rust
我从 The Rust Book 中截取了这张照片和代码。
为什么 s
指向 s1
而不是堆本身的数据?
如果是这样,它是如何工作的? s
如何指向 s1
。是不是分配了内存,ptr字段包含s1
的内存地址。然后,s1
,依次指向数据
在s1
中,我似乎在查看一个带有指针、长度和容量的变量。只有 ptr
字段才是这里的实际指针吗?
这是我的第一个系统级语言,所以我认为与 C/C++ 的比较不会帮助我理解这一点。我认为部分问题是我不太了解指针到底是什么以及 OS allocates/deallocates 内存如何。
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()
}
- memory只是一个巨大的数组,可以通过任何偏移量(例如
u64
)进行索引。
- 此偏移量称为地址,
- 和一个存储地址的变量称为 指针。
- 然而,通常只有一小部分内存被分配,所以并不是每个地址都有意义(或有效)。
- Allocation 是请求使一个(连续的)地址范围对程序有意义(因此它可以access/modify)。
- 每个对象(我所说的对象是指任何类型)都位于分配的内存中(因为非分配的内存对程序没有意义)。
- Reference 实际上是一个(由编译器)保证有效的指针(即从编译器已知的某个对象的地址派生)。也看看 std doc。
这里是这些概念的一个例子 (playground):
// 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 };
我希望能澄清大部分事情,但让我们明确地涵盖问题。
Why does s
point to s1
rather than just the data on the heap itself?
s
是一个引用(即有效指针),所以指向s1
的地址。它可能(并且可能会)被编译器优化为与 s1
相同的一块内存,逻辑上 它仍然是指向 [=13= 的不同对象].
How does the s
point to s1
. Is it allocated memory with a ptr
field that contains the memory address of s1
.
“指向”链仍然存在,因此调用 s.len()
在内部转换为 s.deref().len
,并访问转换为 s.deref().ptr.add(index).deref()
.[=38= 的字符串数组的某些字节]
图片上显示了3块内存:&s
、&s1
、s1.ptr
是不同的(除非优化)内存地址。所有这些都存储在分配的内存中。前两个实际上存储在预先分配的(即在调用 main
函数之前)称为 堆栈 的内存中,通常 它不称为分配的内存 (虽然我在这个答案中忽略了这种做法)。相反,s1.ptr
指针指向用户程序显式分配的内存(即在输入 main
后)。
In s1
, I appear to be looking at a variable with a pointer, length, and capacity. Is only the ptr
field the actual pointer here?
是的,没错。长度和容量只是普通的无符号整数。
我从 The Rust Book 中截取了这张照片和代码。
为什么 s
指向 s1
而不是堆本身的数据?
如果是这样,它是如何工作的? s
如何指向 s1
。是不是分配了内存,ptr字段包含s1
的内存地址。然后,s1
,依次指向数据
在s1
中,我似乎在查看一个带有指针、长度和容量的变量。只有 ptr
字段才是这里的实际指针吗?
这是我的第一个系统级语言,所以我认为与 C/C++ 的比较不会帮助我理解这一点。我认为部分问题是我不太了解指针到底是什么以及 OS allocates/deallocates 内存如何。
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()
}
- memory只是一个巨大的数组,可以通过任何偏移量(例如
u64
)进行索引。 - 此偏移量称为地址,
- 和一个存储地址的变量称为 指针。
- 然而,通常只有一小部分内存被分配,所以并不是每个地址都有意义(或有效)。
- Allocation 是请求使一个(连续的)地址范围对程序有意义(因此它可以access/modify)。
- 每个对象(我所说的对象是指任何类型)都位于分配的内存中(因为非分配的内存对程序没有意义)。
- Reference 实际上是一个(由编译器)保证有效的指针(即从编译器已知的某个对象的地址派生)。也看看 std doc。
这里是这些概念的一个例子 (playground):
// 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 };
我希望能澄清大部分事情,但让我们明确地涵盖问题。
Why does
s
point tos1
rather than just the data on the heap itself?
s
是一个引用(即有效指针),所以指向s1
的地址。它可能(并且可能会)被编译器优化为与 s1
相同的一块内存,逻辑上 它仍然是指向 [=13= 的不同对象].
How does the
s
point tos1
. Is it allocated memory with aptr
field that contains the memory address ofs1
.
“指向”链仍然存在,因此调用 s.len()
在内部转换为 s.deref().len
,并访问转换为 s.deref().ptr.add(index).deref()
.[=38= 的字符串数组的某些字节]
图片上显示了3块内存:&s
、&s1
、s1.ptr
是不同的(除非优化)内存地址。所有这些都存储在分配的内存中。前两个实际上存储在预先分配的(即在调用 main
函数之前)称为 堆栈 的内存中,通常 它不称为分配的内存 (虽然我在这个答案中忽略了这种做法)。相反,s1.ptr
指针指向用户程序显式分配的内存(即在输入 main
后)。
In
s1
, I appear to be looking at a variable with a pointer, length, and capacity. Is only theptr
field the actual pointer here?
是的,没错。长度和容量只是普通的无符号整数。