Rust 入门教程#2:在 Rust 程序中使用变量
在本系列的第一章中,我分享了为什么 Rust 编程语言越来越受欢迎的想法,并展示了如何在 Rust 中编写 Hello World 程序。
让我们继续这个 Rust 之旅。在本文中,我将向您介绍 Rust 编程语言中的变量。
Rust变量的独特性
在编程语言(比如Rust)中,变量是指某些数据存储的内存地址的别名。
这也适用于Rust编程语言。但Rust有一个独特的“特性”。默认情况下,你声明的每个变量都是不可变的。这意味着一旦将值赋给变量,它就无法更改。
这个决定是为了确保默认情况下,您不必像自旋锁或互斥锁这样做特殊处理来引入多线程。Rust保证了安全的并发性。由于所有变量(默认情况下)都是不可变的,因此你不必担心一个线程会无意中更改一个值。
这并不是说Rust中的变量像常量一样,因为它们不是。变量可以显式定义为可变的。这样的变量称为可变变量。
以下是在Rust中声明变量的语法:
// 默认不变性
// 初始化值是**唯一**值
let variable_name = value;
// 使用“mut”关键字定义的可变变量
// 初始值可以更改为其他值
let mut variable_name = value;
虽然您可以更改可变变量的值,但不能将另一种数据类型的值分配给它。
也就是说,如果您有一个浮点型的可变变量,您不能在以后将一个字符分配给它。
Rust的数据类型概述
在上一篇文章中,你可能已经注意到我提到了 Rust 是一种强类型语言。但是在定义变量时,你不需要指定数据类型,而是使用一个通用的关键词 let。
Rust编译器可以根据赋给变量的值推断出数据类型。但是,如果你仍然希望显式地指定数据类型并进行类型注释,也是可以的。以下是语法:
let variable_name: data_type = value;
Rust编程语言中一些常见的数据类型如下:
- 整数类型:i32 和 u32 分别用于有符号和无符号 32 位整数
- 浮点类型:f32 和 f64,分别为 32 位和 64 位浮点数
- 布尔类型:bool
- 字符类型:char
我将在下一篇文章中详细介绍 Rust 的数据类型。目前,这应该足够了。
🚧 Rust不支持隐式类型转换。因此,如果你将值8赋给一个浮点数数据类型的变量,你将会遇到编译时错误。相反,你应该赋值 8. 或 8.0。
Rust还要求在读取存储在变量中的值之前,变量必须先初始化。
{ // 这个块不会编译
let a;
println!("{}", a); // 在这一行上出现了错误
// 读取未初始化变量的值是一个编译时错误
}
{ // 这个代码块可以编译
let a;
a = 128;
println!("{}", a); // 这里没有错误
// 变量'a'有一个初始值
}
如果你声明了一个变量但没有初始化它,在给它赋值之前就使用它的话,Rust编译器会抛出编译时错误。
尽管错误令人讨厌,但在这种情况下,Rust编译器强制你不要犯写代码时常见的错误之一:未初始化变量。
Rust编译器的错误消息
让我们编写一些程序
- 了解如何通过执行“常规”任务来理解Rust的设计,这些任务实际上是与内存相关问题的主要原因
- 阅读和理解Rust编译器的错误/警告消息
测试变量不可变性
我们故意编写一个试图修改可变变量的程序,并查看接下来会发生什么。
fn main() {
let mut a = 172;
let b = 273;
println!("a: {a}, b: {b}");
a = 380;
b = 420;
println!("a: {}, b: {}", a, b);
}
// 更多详细教程 www.linuxmi.com
// 更多详细教程Linux迷 www.linuxmi.com
程序看起来很简单,直到第 4 行。但是在第 7 行,一个不可变变量 b 被修改了它的值。
请注意 Rust 中打印变量值的两种方法。在第 4 行,我用花括号将变量括起来,以便它们的值将被打印。在第 8 行,我保留花括号为空,并将变量作为参数提供,像 C 语言风格。这两种方法都是有效的。(除了修改不可变变量的值,这个程序的一切都是正确的。)
让我们进行编译!(如下图)如果您按照上一章的说明做了,您已经知道如何编译了。
📋“binding”一词指的是变量名,但这只是一个简单化的解释。
这个例子非常好地展示了 Rust 强大的错误检查和信息反馈功能。第一行列出了导致上述代码无法编译的错误信息:
error[E0384]: cannot assign twice to immutable variable b
这意味着 Rust 编译器注意到我试图将一个新值赋给变量 b,但是变量 b 是一个不可变变量,所以会导致这个错误。
编译器甚至标出了错误出现的确切行和列号。
在提示信息的下一行,说的是“第一次为 b
赋值的行”,并提供了帮助。由于我正在修改不可变变量 b 的值,因此被告知要使用 mut 关键字将变量 b 声明为可变变量。
🖥️ 自己实现一个修复方案,更好地理解手头的问题。
使用未初始化的变量
现在,让我们看一下当读取未初始化变量的值时Rust编译器会发生什么。
fn main() {
let a: i32;
a = 123;
println!("a: {a}");
let b: i32;
println!("b: {b}");
b = 123;
}
// 更多详细教程 www.linuxmi.com
// 更多详细教程Linux迷 www.linuxmi.com
在这里,我声明了两个不可变变量a和b,两者都未初始化。在读取变量a的值之前,将变量a赋值。但是在给变量b赋初始值之前,已经读取了变量b的值。
让我们编译并查看结果,如下图:
在这里,Rust 编译器会抛出一个编译时错误和一个警告。警告指出变量 b 的值从未被读取过。
但这是荒谬的!变量 b 的值在第 7 行被访问了。但是请仔细看,警告是针对第 8 行的。这很令人困惑;让我们暂时跳过这个警告,看看错误信息。
错误消息显示 used binding b
is possibly-uninitialized。与前面的例子一样,Rust 编译器指出读取变量 b 的值是错误的,原因是其值未初始化,在Rust编程语言中是不合法的,因此会出现编译时错误。
🖥️ 通过交换第7行和第8行的代码,可以轻松解决此错误。尝试一下,看看错误是否消失。如下图:
示例程序:交换数字
现在你已经熟悉了常见的与变量相关的问题,让我们看一个交换两个变量的值的程序。
fn main() {
let mut a = 7186932;
let mut b = 1276561;
println!("a: {a}, b: {b}");
// 交换值
let temp = a;
a = b;
b = temp;
println!("a: {}, b: {}", a, b);
}
// 更多详细教程 www.linuxmi.com
// 更多详细教程Linux迷 www.linuxmi.com
这里,我声明了两个变量a和b。两个变量都是可变的,因为我希望在以后改变它们的值。我分配了一些随机的值。最初,我打印这些变量的值。
然后,在第8行,我创建了一个不可变的变量temp,并将存储在a中的值赋给它。之所以这个变量是不可变的,是因为temp的值不会改变。
为了交换值,我将变量b的值赋给变量a,然后在下一行将temp的值(它包含a的值)赋给变量b。现在值已经交换,我打印变量a和b的值。
当编译并执行以上代码时,我得到以下输出:
如您所见,值已经交换了,完美。
使用但尚未使用的变量
在编译 Rust 代码时,如果您已经声明了一些打算在下一步中使用但尚未使用的变量,则 Rust 编译器会对此发出警告。
原因很明显。未使用的变量占用不必要的初始化时间(CPU 周期)和内存空间。如果不会使用它,为什么要在程序中使用它呢?尽管编译器会对其进行优化,但它仍然存在代码冗余的可读性问题。
但有时,您可能会遇到无法创建变量的情况。例如,当一个函数返回多个值,而您只需要其中的一些值时。在这种情况下,您无法告诉库维护者根据您的需求调整其函数。
因此,在这种情况下,您可以使用以下划线开头的变量,Rust 编译器将不再给您提供此类警告。如果您确实不需要甚至使用存储在未使用变量中的值,可以将其简单地命名为 _(下划线),Rust 编译器也将忽略它!
以下程序不仅不会生成任何输出,而且也不会生成任何警告和/或错误消息:
fn main() {
let _unnecessary_var = 0; // 没有警告信息
let _ = 0.0; // 完全被忽略
}
算术运算
由于数学就是数学,Rust 并没有在数学方面进行创新。您可以使用所有可能在其他编程语言中使用过的算术运算符,如 C、C++ 或 Java。
可以在此处找到 Rust 编程语言中所有操作的完整列表,以及它们的含义。
示例程序:Rusty 温度计
以下是一个典型的程序,将华氏温度转换为摄氏温度,反之亦然。
fn main() {
let boiling_water_f: f64 = 212.0;
let frozen_water_c: f64 = 0.0;
let boiling_water_c = (boiling_water_f - 32.0) * (5.0 / 9.0);
let frozen_water_f = (frozen_water_c * (9.0 / 5.0)) + 32.0;
println!(
"水在沸腾时的温度为 {}°C (或 {}°F).",
boiling_water_c, boiling_water_f
);
println!(
"水在结冰时的温度为 {}°C (或 {}°F).",
frozen_water_c, frozen_water_f
);
}
// 更多详细教程 www.linuxmi.com
// 更多详细教程Linux迷 www.linuxmi.com
这里并没有什么复杂的内容…这个程序将华氏温度转换为摄氏温度,反之亦然。
正如您在这里看到的,由于 Rust 不允许自动类型转换,我不得不在 32、9 和 5 这些整数后面加上小数点。除此之外,这与您在 C、C++ 或 Java 中所做的类似。
作为一个学习练习,尝试编写一个程序,找出给定数字中有多少位数字。
请继续关注:Rust 入门教程系列:https://www.linuxmi.com/tag/rustjiaocheng
The post Rust 入门教程#2:在 Rust 程序中使用变量 first appeared on Linux迷.
共有 0 条评论