字符串文字是不可变的吗?

问题描述 投票:0回答:1

我正在阅读 Rust 书来学习 Rust,目前正在学习所有权。它提到:

我们已经看到了字符串文字,其中字符串值是硬编码的 进入我们的程序。字符串字面量很方便,但实际上并非如此 适用于我们可能想要使用文本的每种情况。一 原因是它们是不可变的。

下面的代码运行没有任何问题。在这里我改变了

a
的值,如果不可变字符串可以改变那里说明的问题是什么?

fn main() {
   let mut a = "Hello";
   println!("{}", a);
   a = " World";
   println!("{}", a);
}
rust immutability string-literals
1个回答
5
投票

rust 编译器生成的可执行二进制文件在只读数据部分包含字符串文字“Hello”和“World”

rodata
.

$ cargo build --release
$ readelf -x .rodata target/release/demo | grep Hello
  0x0003c000 48656c6c 6f000000 0a576f72 6c640000 Hello....World..

因为这些字面量被放在一个不可变的部分,所以操作系统禁止修改它们。

fn main() {
    let mut a: &'static str = "Hello";
    println!("{}", a);

    unsafe { (a.as_ptr() as *mut u8).write(42) };
    println!("{}", a);
}
$ cargo run
Hello
Segmentation fault

但是,variable

a
&str
类型,所以是一个指向字符串切片的指针,它存在于堆栈中。因此,
a
先指向“Hello”的地址,再指向“World”的地址是完全有效的。


编辑:关于

unsafe
块的信息

我们想在

a
指向的地址写入一些东西,以表明它确实存储在只读部分。

a
被声明为
mut a: &str
,这意味着变量是可变的,但数据(字符串文字)是不可变的(与
mut a: &mut str
😉️相反)。 因此,编译器阻止我们使用
a.as_mut_ptr()
来获取指向底层字节的可变(又名可写)指针。

相反,我们必须做一个小技巧:使用

a.as_ptr()
并将返回的
const *u8
转换为
mut *u8
。最后,写入指针需要一个
unsafe
块,因为你可能会违反 Rust 的内存安全,这可能会导致不好的事情发生,如上面所示的分段错误。

© www.soinside.com 2019 - 2024. All rights reserved.