我试着去理解Rust的指针/引用系统和C的比较。我已经包含了 * 大致 * 相同的Rust和C代码以及它们的输出。代码的目的是声明一个“字符串”,声明一个指向字符串的第一个元素/字符的指针,然后为每个元素:
1.打印原始指针(内存地址)
1.打印字符本身(通过取消引用指针)
1.再次打印存储器地址(通过参考从步骤2获得的值)
所有的步骤在C中都能正常工作,但是第三步在Rust中却不能正常工作。我怎样才能在Rust中像这样操作不安全的指针算法呢?(例如创建指针;参考参考)
** rust eclipse 源**
fn main() {
//Init String, pointer and get String length for iterator
let my_str = String::from("York");
let my_str_ptr: *const u8 = my_str.as_ptr();
println!("Original string: {my_str}");
for i in 0..my_str.len() {
unsafe {
//Offset pointer by i
let chr_ptr: *const u8 = my_str_ptr.offset(i as isize);
let chr: char = *chr_ptr as char;
println!("Deref raw pointer: {chr}");
println!("Raw pointer: {chr_ptr:p}");
println!("Ref to value: {:p}", &chr);
}
}
}
** rust eclipse 量:**
Original string: York
Deref raw pointer: Y
Raw pointer: 0x561e134b8ba0
Ref to value: 0x7ffd962f665c
Deref raw pointer: o
Raw pointer: 0x561e134b8ba1
Ref to value: 0x7ffd962f665c
Deref raw pointer: r
Raw pointer: 0x561e134b8ba2
Ref to value: 0x7ffd962f665c
Deref raw pointer: k
Raw pointer: 0x561e134b8ba3
Ref to value: 0x7ffd962f665c
C来源:
#include <stdio.h>
int main(void) {
char *my_str = "York";
char *my_str_ptr = my_str;
printf("Original string: %s\n", my_str);
while (*my_str_ptr != '\0') {
printf("Deref raw pointer: %p\n", my_str_ptr);
printf("Raw pointer: %c\n", *my_str_ptr);
printf("Ref to value: %p\n\n", &(*my_str_ptr));
my_str_ptr++;
}
return 0;
}
C输出:
Original string: York
Deref raw pointer: 0x559af0d44004
Raw pointer: Y
Ref to value: 0x559af0d44004
Deref raw pointer: 0x559af0d44005
Raw pointer: o
Ref to value: 0x559af0d44005
Deref raw pointer: 0x559af0d44006
Raw pointer: r
Ref to value: 0x559af0d44006
Deref raw pointer: 0x559af0d44007
Raw pointer: k
Ref to value: 0x559af0d44007
在这个极其简单的例子中可以清楚地看到,在C中分层ref/deref操作符是很简单的,这样就可以获得值和它们的引用,然而对于rust中的char来说,情况似乎不是这样。
我怀疑这是由Rust的打印格式化程序引起的,这个问题与Rust实现指针、值和地址的方式无关。
1条答案
按热度按时间ccrfmcuu1#
下面的答案和代码反映了cafce 25所做的评论,它回答了我最初的问题并解决了我的困惑。
C代码和Rust代码并不等同,C代码直接作用于迭代块中的global/main()定义的变量,而Rust代码在每次迭代时都会创建一个新的局部作用域char,并正确打印。
然而,当打印单个char的内存地址时--输出显示的是局部作用域char的地址,每次for循环迭代时都会重新创建该地址;这只是碰巧编译器重用相同的堆栈地址来存储char的情况。
固定 rust eclipse 代码:
固定 rust eclipse 程序输出: