博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接
博客内容主要围绕:
5G/6G协议讲解
高级C语言讲解
Rust语言讲解
文章目录
- [Rust 基础数据类型介绍------指针、元组和布尔类型](#Rust 基础数据类型介绍——指针、元组和布尔类型)
Rust 基础数据类型介绍------指针、元组和布尔类型
一、元组类型
元组是各种类型的值的一个序列,序列中的每个元素用逗号分隔开并包裹在一个圆括号中 。例如 ("Brazil", 1995) 是一个元组,其第一个元素是一个静态分配的字符串,第二个元素是一个整数,它的类型是 (&str, i32) 。给定一个元组值 t ,可以通过 t.0 、t.1 等访问其元素。
元组有点儿像数组,即这两种类型都表示值的有序序列。与数组不同的是:
- 元组的每个元素可以是不同的类型,而数组的元素必须都是相同的类型;
- 元组只允许用常量作为索引,例如 t.4。不能通过写成 t.i 或者 t[i] 的形式来获取第 i 个元素;
Rust 通常会使用元组类型从一个函数返回多个值,例如字符串切片上的 split_at 方法会将字符串分成两半并返回它们,其声明如下所示:
rust
fn split_at(&self, mid: usize) -> (&str, &str);
返回类型为 (&str, &str) 是两个字符串切片构成的元组,可以使用模式匹配语法将返回值的每个元素赋值给不同的变量:
rust
let text = "I see the eigenvalue in thine eye";
let (head, tail) = text.split_at(21);
assert_eq!(head, "I see the eigenvalue ");
assert_eq!(tail, "in thine eye");
另一种常用的元组类型是零元组()
。通常也称为单元类型 ,因为此类型只有一个值,写作 () 。当无法携带任何有意义的值但其上下文仍然要求传入某种类型时,Rust就会使用单元类型。例如,不返回值的函数的返回类型为() 。标准库的 std::mem::swap 函数就没有任何有意义的返回值,它只会交换两个参数的值,其声明如下所示:
rust
fn swap<T>(x: &mut T, y: &mut T);
其中的 <T> 意味着 swap是泛型的:可以将对任意类型T的值的引用传递给它,但是上述的声明省略了swap的返回类型,其完整的声明如下所示:
rust
fn swap<T>(x: &mut T, y: &mut T) -> ();
类似地,如果返回类型是 Result< (), std::io::Error > ,这意味着该函数在出现错误时会返回一个 std::io::Error 值,但成功时不会返回任何值。
Rust允许在任何出现逗号的位置,例如,函数参数、数组、元组、结构体和枚举定义等,添加额外的尾随逗号 。对于单个值的元组,例如,("lonely hearts",) ,其只包含一个值且这个值后面的逗号是必需的,用于区分单值元组和简单的括号表达式。
二、指针类型简介
2.1 引用
在Rust中可以将引用视为基本指针类型。在运行期时,对 i32 的引用是一个保存着 i32 地址的机器字,这个地址可能位于栈或堆中。表达式 &x 会生成一个对 x 的引用,在 Rust 术语中,我们会说它借用了对 x 的引用。给定一个引用 r,表达式 *r 会引用 r 指向的值。它们非常像 C 和 C++ 中的 & 运算符和 * 运算符,并且和 C 中的指针一样,当超出作用域时引用不会自动释放任何资源。
然而,与C指针不同,Rust的引用永远不会为空,在安全的Rust中根本没办法生成空引用。与C不同,Rust会跟踪值的所有权和生命周期,因此早在编译期间就排除了悬空指针、双重释放和指针失效等错误。
Rust 引用有两种形式:
- &T:不可变的共享引用。可以同时拥有多个对给定值的共享引用,但它们是只读的,禁止修改它们所指向的值,就像C中的 const T* 一样;
- &mut T:可变且独占的引用。可以读取和修改它指向的值,就像C语言中的 T* 一样。但是只要该引用还存在,就不能对该值有任何类型的其他引用。事实上,访问该值的唯一途径就是使用这个可变引用。
Rust使用共享引用和可变引用之间的二选一机制,来强制执行单个写入者或多个读取者规则。
2.2 Box
在堆中分配内存最简单的方式是使用 Box::new
,如下代码所示:
rust
let t = (12, "eggs");
let b = Box::new(t); //在堆中分配一个元组
上面代码中,t 的类型是 (i32, &str),所以 b 的类型是 Box<(i32, &str)>。对 Box::new 的调用会分配足够的内存以在堆上容纳此元组。当 b 超出作用域时,内存会立即释放,除非 b 已被移动(move)。
2.3 裸指针
Rust 也有裸指针类型 *mut T
和 *const T
。裸指针实际上和 C++ 中的指针很像。使用裸指针是不安全的,因为 Rust 不会跟踪它指向的内容。例如,裸指针可能为空,或者它们可能指向已释放的内存或现在包含不同类型的值。只能在 unsafe
块中对裸指针解引用。
三、布尔类型
Rust 中的布尔类型bool
具有此类型常用的两个值true
和false
。==
、<
等比较运算符会生成 bool 结果,比如 2 < 5 的值为 true。
许多语言对要求布尔值的上下文中使用其他类型的值持宽松态度,比如C和C++会把字符、整数、浮点数和指针隐式转换为布尔值,因此它们可以直接用作 if 语句或 while 语句中的条件。Python 允许在布尔上下文中使用字符串、列表、字典甚至集合,如果这些值是非空的,则将它们视为 true。然而,Rust 非常严格,**像 if 和 while 这样的控制结构要求它们的条件必须是 bool 表达式,短路逻辑运算符 && 和 || 也是如此。你必须写成 if x != 0 {...} ,而不能只写成 if x {...}。
Rust 中的 as
运算符可以将 bool 值转换为整数:
rust
assert_eq!(false as i32, 0);
assert_eq!(true as i32, 1);
但是,as 无法进行另一个方向的转换,例如,从数值类型转换为bool。相反,你必须显示的写出比较表达式,比如 x != 0。
尽管 bool 只需要用一个位来表示,但 Rust 在内存中会使用整字节来表示 bool 值,因此可以创建指向它的指针。
四、类型别名
与 C++ 中的 typedef 用法类似,可以使用 type
关键字来为现有类型声明一个新名称:
rust
type Bytes = Vec<u8>;
上面声明的类型 Bytes 就是这种特定 Vec 的简写形式。
rust
fn decode(data: &Bytes) {
...
}