&str与String
&str代表不可变的字符切片&[u8]。
String是堆上的Vec
&str => String
let str: String = "abc".to_string();
let str: String = String::from("abc");
String => &str
let str: &str = &*String::from("abc"); // 注意这里先解引用再取引用
let str: &str = String::from("abc").as_str(); // 不推荐,字符串是临时的,无法使用
字符与字符串
Rust使用UTF-8编码。对于ASCII或者其超集ISO-8859-1(Latin-1)字符,还可以使用r"[a-zA-Z]"
来声明。
str.as_ptr(); // *const u8
str.as_bytes(); // &[u8]
str.as_bytes_mut(); // &mut [u8] 不安全
str.len(); // byte length
let chs: Vec<char> = str.chars().collect(); // 获取字符数组
str.chars().nth(0); // 获取第n个char(一个char表示一个Unicode一个代码点)
字符串的比较和匹配
fn main() -> std::io::Result<()> {
let str1: String = String::from("abc");
let str2: String = String::from("abc");
println!("equals? {}", str1.eq(&str2)); // 比较
println!("equals? {}", str1 == str2); // 可直接==比较
match str1.as_str() { // 匹配最好转为字符切片
"abc" => {
println!("abc");
}
_ => {}
}
Ok(())
}
指针
引用其实可以转换为指针:
fn main() -> std::io::Result<()> {
let a = 8;
let b = &a as *const i32 as *mut i32;
unsafe {
*b = 99;
}
println!("a = {0}", a); // 99
Ok(())
}
关于字符切片:
// 引用强转指针
fn main() -> std::io::Result<()> {
let a: &str = "this is a &[str]"; // a虽然是一个引用,其实是一个指向str切片的指针变量
let p0: *const str = a as *const str; // a强转为常指针,得到str的起始地址
let p1: *const *const str = &a as *const &str as *const *const str; // 取a变量的引用,先强转为指向&str的常指针,再强转为指向str切片指针的指针
// error:
// let p1: *const *const str = &a as *const *const str; // 不可一步转完
println!("{:p} {:p} {:p}", p0, p1, &a); // 后二者相等
let p2: *const str = &a[..2][..][..];
println!("{:p}", p2);
// 指针失去了切片的长度记忆能力
// println!("{}", p2); // 无法编译
let pr: &str = &a[..2][..][..];
println!("{}", pr); // 正常打印字符切片
Ok(())
}
/*
0x7ff7f02ef3e8 0x49a5fcf990 0x49a5fcf990
0x7ff7f02ef3e8
th
*/
size_of
println!("{}", std::mem::size_of::<*const i8>());