欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 生信小白学Rust-02

生信小白学Rust-02

2025/4/21 8:51:11 来源:https://blog.csdn.net/weixin_53737233/article/details/147288868  浏览:    关键词:生信小白学Rust-02

基本类型

Rust 每个值都有其确切的数据类型,总的来说可以分为两类:基本类型和复合类型。 基本类型意味着它们往往是一个最小化原子类型,无法解构为其它类型(一般意义上来说),由以下组成:

  • 数值类型:有符号整数 (i8, i16, i32, i64, isize)、 无符号整数 (u8, u16, u32, u64, usize) 、浮点数 (f32, f64)、以及有理数、复数

有符号整数:二进制补码表示,包含正负数;每个有符号类型规定的数字范围是 -(2^n - 1) ~ 2^n - 1 - 1;i8范围为-128~127;isize(指针大小,32位系统=i32,64位系统=i64)

无符号整数:仅表示非负数;u8范围为0~255

浮点数:小心浮点数陷阱

  • 字符串:字符串字面量和字符串切片 &str
  • 布尔类型:truefalse
  • 字符类型:表示单个 Unicode 字符,存储为 4 个字节;Rust 的字符只能用 '' 来表示, "" 是留给字符串的。

Rust 的字符不仅仅是 ASCII,所有的 Unicode 值都可以作为 Rust 字符,包括单个的中文、日文、韩文、emoji 表情符号等等,都是合法的字符类型。Unicode 值的范围从 U+0000 ~ U+D7FFU+E000 ~ U+10FFFF

  • 单元类型:即 () ,其唯一的值也是 ()

数字运算

fn main() {// 编译器会进行自动推导,给予twenty i32的类型let twenty = 20;// 类型标注let twenty_one: i32 = 21;// 通过类型后缀的方式进行类型标注:22是i32类型let twenty_two = 22i32;// 只有同样类型,才能运算let addition = twenty + twenty_one + twenty_two;println!("{} + {} + {} = {}", twenty, twenty_one, twenty_two, addition);// 对于较长的数字,可以用_进行分割,提升可读性let one_million: i64 = 1_000_000;println!("{}", one_million.pow(2));// 定义一个f32数组,其中42.0会自动被推导为f32类型let forty_twos = [42.0,42f32,42.0_f32,];// 打印数组中第一个值,并控制小数位为2位println!("{:.2}", forty_twos[0]);
}

序列

Rust 提供了一个非常简洁的方式,用来生成连续的数值,例如 1..5,生成从 1 到 4 的连续数字,不包含 5 ;1..=5,生成从 1 到 5 的连续数字,包含 5,它的用途很简单,常常用于循环中:

for i in 1..=5 {println!("{}",i);
}

常量(constant)

  • 常量不允许使用 mut。常量不仅仅默认不可变,而且自始至终不可变,因为常量在编译完成后,已经确定它的值。
  • 常量使用 const 关键字而不是 let 关键字来声明,并且值的类型必须标注。
// Rust 常量的命名约定是全部字母都使用大写,并使用下划线分隔单词,
// 另外对数字字面量可插入下划线以提高可读性
const MAX_POINTS: u32 = 100_000;

变量可变

还是第一次听这种说法🤭

Rust 的变量在默认情况下是不可变的。前文提到,这是 Rust 团队为我们精心设计的语言特性之一,让我们编写的代码更安全,性能也更好。当然你可以通过 mut 关键字让变量变为可变的,让设计更灵活。

fn main() {let x = 5;println!("the value of x is :{}", x);let x = 4;println!("the value of x is :{}", x);x = 6;println!("the value of x is :{}", x);
}

这样会得到报错信息:

(base) PS D:\000zyf\Learning\rust_learn\variables> cargo runCompiling variables v0.1.0 (D:\000zyf\Learning\rust_learn\variables)
error[E0384]: cannot assign twice to immutable variable `x`--> src\main.rs:6:5|
4 |     let x = 4;|         - first assignment to `x`
5 |     println!("the value of x is :{}", x);
6 |     x = 6;|     ^^^^^ cannot assign twice to immutable variable|
help: consider making this binding mutable|
4 |     let mut x = 4;|         +++For more information about this error, try `rustc --explain E0384`.
error: could not compile `variables` (bin "variables") due to 1 previous error

具体的错误原因是 cannot assign twice to immutable variable x(无法对不可变的变量进行重复赋值),因为我们想为不可变的 x 变量再次赋值。

这种错误是为了避免无法预期的错误发生在我们的变量上:一个变量往往被多处代码所使用,其中一部分代码假定该变量的值永远不会改变,而另外一部分代码却无情的改变了这个值,在实际开发过程中,这个错误是很难被发现的,特别是在多线程编程中。

不过要想让某一变量可以被改变也很简单,只需要用mut就好,像下面这样:

fn main() {let x = 5;println!("the value of x is :{}", x);let mut x = 4;println!("the value of x is :{}", x);x = 6;println!("the value of x is :{}", x);
}// (base) PS D:\000zyf\Learning\rust_learn\variables> cargo run
//    Compiling variables v0.1.0 (D:\000zyf\Learning\rust_learn\variables)
//     Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.04s
//      Running `target\debug\variables.exe`
// the value of x is :5
// the value of x is :4
// the value of x is :6

补充

在编写代码进行学习的时候,无意中将第二个变量前面也加了let,按理来第一次没加mut这个代码应该报错的,但却成功运行了,又稍微了解了一下:

Rust变量遮蔽与可变性解析

工作正常的代码分析

fn main() {let x = 5;                          // x 是不可变的,值为5println!("the value of x is :{}", x);let mut x = 4;                      // 创建一个新的可变变量x,遮蔽(shadow)了原来的xprintln!("the value of x is :{}", x);x = 6;                              // 可以修改这个可变的xprintln!("the value of x is :{}", x);
}

这段代码能够正常工作是因为:

第一个 x 是不可变的,值为5

使用 let mut x = 4 声明了一个全新的变量 x,它遮蔽了之前的 x

这个新的 x 是可变的(mut),所以后续的 x = 6 赋值操作是合法的

无法工作的代码分析

fn main() {let mut x = 5;                     // x 是可变的,值为5println!("the value of x is :{}", x);let x = 4;                         // 创建一个新的不可变变量x,遮蔽了原来的xprintln!("the value of x is :{}", x);x = 6;                             // 错误!新的x是不可变的,不能被修改println!("the value of x is :{}", x);
}

这段代码无法工作的原因是:

第一个 x 虽然是可变的,但它随后被遮蔽了

第二个 let x = 4 创建了一个新的变量,默认是不可变的(没有使用mut关键字)

当尝试 x = 6 时,编译器会报错,因为当前作用域中的 x 是不可变的

核心概念

变量遮蔽:在Rust中,使用let关键字重新声明同名变量会创建一个全新的变量,完全遮蔽之前的变量

变量可变性:每个新变量的可变性由其声明时是否使用mut关键字决定,与被遮蔽的同名变量无关

要修复第二个例子,可以将第二个声明改为 let mut x = 4;,这样后续的赋值操作就合法了。

变量遮蔽的用处在于,如果你在某个作用域内无需再使用之前的变量(在被遮蔽后,无法再访问到之前的同名变量),就可以重复的使用变量名字,而不用绞尽脑汁去想更多的名字。


选择可变还是不可变,更多的还是取决于你的使用场景,例如不可变可以带来安全性,但是丧失了灵活性和性能(如果你要改变,就要重新创建一个新的变量,这里涉及到内存对象的再分配)。而可变变量最大的好处就是使用上的灵活性和性能上的提升。

例如,在使用大型数据结构或者热点代码路径(被大量频繁调用)的情形下,在同一内存位置更新实例可能比复制并返回新分配的实例要更快。使用较小的数据结构时,通常创建新的实例并以更具函数式的风格来编写程序,可能会更容易理解,所以值得以较低的性能开销来确保代码清

忽略未使用变量

告诉 Rust 不要警告未使用的变量,为此可以用下划线作为变量名的开头

fn main() {let _x = 5;let y = 10;
}// warning: unused variable: `y`
//  --> src/main.rs:3:9
//   |
// 3 |     let y = 10;
//   |         ^ help: 如果 y 故意不被使用,请添加一个下划线前缀: `_y`
//   |
//   = note: `#[warn(unused_variables)]` on by default

变量解构

let 表达式不仅仅用于变量的绑定,还能进行复杂变量的解构:从一个相对复杂的变量中,匹配出该变量的一部分内容:

fn main() {let (a, mut b): (bool,bool) = (true, false);// a = true,不可变; b = false,可变println!("a = {:?}, b = {:?}", a, b);b = true;assert_eq!(a, b);
}
// a = true, b = false

解构式赋值

struct Struct {e: i32
}fn main() {let (a, b, c, d, e);(a, b) = (1, 2);// _ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有使用一个变量名而是使用了 _[c, .., d, _] = [1, 2, 3, 4, 5];Struct { e,.. } = Struct { e: 5 };assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);println!("{}",a)
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词