Rust 笔记:Rust 语言中的运算符

简介: Rust 笔记:Rust 语言中的运算符



1. 概述

在各种编程语言中,运算符(Operators)是用于执行各种操作的符号或关键字。它们可以用于操作数据、执行逻辑判断、进行赋值等。根据其功能和操作数的数量,运算符可以被分类为以下几种类型:

  1. 一元运算符:一元运算符作用于单个操作数,对其进行特定操作或计算。
  2. 二元运算符:二元运算符作用于两个操作数,对其进行特定操作或计算。
  3. 三元运算符:三元运算符是一种特殊的运算符,接受三个操作数,并根据第一个操作数的条件返回第二个或第三个操作数。

注:Rust 语言中无三元运算符。

  1. 逻辑运算符:逻辑运算符用于执行逻辑操作,例如逻辑与、逻辑或和逻辑非。
  2. 比较运算符:比较运算符用于比较两个值之间的关系,并返回布尔值(true 或 false)。
  3. 算术运算符:算术运算符用于执行数学运算,如加法、减法、乘法和除法等。
  4. 位运算符:位运算符用于对二进制位进行操作,如按位与、按位或、按位异或等。
  5. 索引运算符:它需用于从 被索引的操作数 凭借 索引值 获取结果返回。

以上的类别是有重叠的,比如 逻辑运算符 等也是一元运算符, 算术运算符索引运算符 等同时也是 二元运算符。在本文的介绍中,如果在前面的类别中已经讲解过,则后文不再重复讲解。

2. 一元运算符

2.1 关于 一元运算符

一元运算符Unary Operators)又称之为单目运算符,指的是只对一个表达式执行操作,该表达式可以是数值数据类型类别中的任何一种数据类型。Rust 语言 中的一元运算符包括 加(+)减(-)、**逻辑非(!)**和 取地址(&) 等。但是整体上看,都可以视为一元或者二元运算符,并且 rust 语言不提供内置的三元操作符。

2.2 正(+)运算符

【注意】:+ 用于 取正 时为 一元运算符,但是用于 加法 时则为 二元运算符。另请参见 [加运算符

加(+) 运算符 用于对操作数 取正,其实没有实际变化。

let a = 10;
let b = +a; // 取 a 的正值(实际上没有变化)
println!("b: {}", b); // 输出: b: 10

2.3 负(-)运算符

负(-) 运算符 用于用于对操作数取负。例如:

let a = 10;
let b = -a; // 取 a 的负值
println!("b: {}", b); // 输出: b: -10

2.4 逻辑非(!)运算符

逻辑非(!) 运算符 用于 对 布尔类型 的操作数 取反。包括以下两种情况:

  • 如果操作数的值为 true,则将 true 变为 false
  • 如果操作数的值为 false,则将 false 变为 true

例如:

let a = true;
let b = !a;           // 对 a 取逻辑非
println!("b: {}", b); // 输出: b: false

2.5 递增(++)和递减(–)运算符

递增(++) 和 **递减(–)**运算符 分别用于 对操作数 进行 自增自减 操作。例如:

// 自增操作
let mut a = 10;
a += 1;               // 等价于 a = a + 1
println!("a: {}", a); // 输出: a: 11
// 自减操作
let mut b = 5;
b -= 1;               // 等价于 b = b - 1
println!("b: {}", b); // 输出: b: 4

2.6 取址(&)运算符

取址(&) 运算符用于 获取变量的内存地址。例如:

let a = 10;
let b = &a; // 获取变量 a 的内存地址
println!("b: {:?}", b); // 输出: b: 0x7ffc8680d1b8(具体的地址可能不同)

2.7 解引用(*)运算符

解引用运算符 * 用于从 引用类型 中获取 引用所指向的值。它允许你访问引用类型中存储的实际值。

例如:

let num = 42;
let num_ref = #
let dereferenced_num = *num_ref;                    // 使用解引用运算符获取引用所指向的值
println!("Dereferenced num: {}", dereferenced_num); // 输出: Dereferenced num: 42
let mut value = 10;
let value_ref = &mut value;
*value_ref = 20;                       // 使用解引用运算符修改引用所指向的值
println!("Modified value: {}", value); // 输出: Modified value: 20

3. 二元运算符

3.1 关于 二元运算符

类似地,二元运算符(Binary Operators)是一种作用于两个操作数的运算符。在各种编程语言中一般用于表示由两个元素形成第三个元素的一种规则,它们往往用于执行各种操作,如加法、减法、乘法、除法、逻辑运算等。

Rust 语言中,对二元运算符进行细分还可以分为:

  1. 算术运算符:用于执行数值计算;
  2. 逻辑运算符:用于执行逻辑操作;
  3. 赋值运算符:用于将 右侧的值 赋给 左侧的变量;
  4. 比较运算符:用于对两个值进行比较并得出结论;

3.2 算术运算符

3.2.1 加法(+)运算符

加法(+) 运算符用于对两个操作数进行相加。例如:

let a = 5;
let b = 3;
let c = a + b; // 将 a 和 b 相加
println!("c: {}", c); // 输出: c: 8

3.2.1 减法(-)运算符

减法(-) 运算符用于从第一个操作数中减去第二个操作数。例如:

let a = 5;
let b = 3;
let c = a - b; // 从 a 中减去 b
println!("c: {}", c); // 输出: c: 2

3.2.3 乘法(*)运算符

乘法(*) 运算符用于将两个操作数相乘。例如:

let a = 5;
let b = 3;
let c = a * b; // 将 a 和 b 相乘
println!("c: {}", c); // 输出: c: 15

3.2.3 除法(/)运算符

除法(/) 运算符用于将第一个操作数除以第二个操作数。例如:

let a = 10;
let b = 2;
let c = a / b; // 将 a 除以 b
println!("c: {}", c); // 输出: c: 5

3.3 逻辑运算符

3.3.1 逻辑与(&&)

逻辑与(&&) 运算符 用于对两个布尔类型的操作数进行逻辑与操作。例如:

let a = true;
let b = false;
let c = a && b;         // 对 a 和 b 执行逻辑与操作
println!("c: {}", c);   // 输出: c: false

3.3.2 逻辑或(||)

逻辑或(||) 运算符用于对两个布尔类型的操作数进行逻辑或操作。例如:

let a = true;
let b = false;
let c = a || b;        // 对 a 和 b 执行逻辑或操作
println!("c: {}", c);  // 输出: c: true

3.4 比较运算符

3.4.1 等于(==)

相等性(==) 运算符用于检查两个操作数是否相等。例如:

let a = 2;
let b = 2;
let c = a == b;        // 检查 a 和 b 是否相等
println!("c: {}", c);  // 输出: c: true

3.4.2 不等于(!=)

不相等(!=) 运算符用于检查两个操作数是否不等。例如:

let a = 1;
let b = 3;
let c = a != b;         // 检查 a 和 b 是否不相等
println!("c: {}", c);   // 输出: c: true

3.4.3 大于运算符(>)

大于运算符(>) 用于检查左操作数是否大于右操作数。

let a = 2;
let b = 1;
let result = a > b;  // 结果为 true

3.4.4 小于运算符(<)

小于运算符(<) 用于 检查左操作数是否小于右操作数。例如:

let a = 2;
let b = 1;
let result = a < b;    // 结果为 false

3.4.5 大于等于运算符(>=)

大于等于运算符(>=) 用于检查左操作数是否大于或等于右操作数。例如:

let a = 2;
let b = 1;
let result = a >= b;    // 结果为 true

3.4.6 小于等于运算符(<=)

小于等于运算符(<=) 用于检查左操作数是否小于或等于右操作数。例如:

let a = 2;
let b = 1;
let result = a <= b;    // 结果为 false

3.5 赋值运算符

3.5.1 基本赋值(=)运算符

赋值(=) 运算符 用于将右侧的值赋给左侧的变量。例如:

let a = 1;             // 将值 1 赋给变量 a

3.5.2 复合赋值运算符(如 +=、-=、*=、/= 等)

在赋值运算符的基础上,结合其它运算符就形成了功能略多的 复合赋值运算符(如 +=、-=、*=、/= 等)。 复合赋值运算符用于将运算符右侧的值与左侧的变量进行运算,并将结果赋给左侧的变量。

let mut a = 1;
a += 2;               // 等价于 a = a + 2
println!("a: {}", a); // 输出: a: 3

3.6 位运算符

位运算符用于对整数类型的二进制位进行操作,也有两个操作数,因此同样可视为二元运算符。在 Rust 语言中,位运算符包括:

  • 按位与运算符(&)
  • 按位或运算符(|)
  • 按位异或运算符(^)
  • 左移运算符(<<)
  • 右移运算符(>>)

3.6.1 按位与(&)运算符

按位与运算符(&)用于对两个操作数的对应二进制位进行与操作,结果为每个对应位都为1时才为1,否则为0。

let a = 2;
let b = 3;
let result = a & b;  // 对 a 和 b 的二进制位进行与操作

3.6.2 按位或(|)运算符

按位或运算符(|)用于对两个操作数的对应二进制位进行或操作,结果为每个对应位都为0时才为0,否则为1。

let a = 5;
let b = 3;
let result = a | b; // 对 a 和 b 的二进制位进行或操作

3.6.3 按位异或(^)运算符

按位异或运算符(^)用于对两个操作数的对应二进制位进行异或操作,结果为每个对应位相同为0,不同为1。

let a = 5;
let b = 3;
let result = a ^ b; // 对 a 和 b 的二进制位进行异或操作

3.6.4 左移(<<)运算符

左移运算符(<<)用于将操作数的二进制位向左移动指定的位数,右侧空出的位用0填充。

例如:

let a = 5;            // 二进制表示为 0101
let result = a << 2;  // 将二进制位左移2位,结果为 10100,即 20

3.6.5 右移(>>)运算符

右移运算符(>>)用于将操作数的二进制位向右移动指定的位数,左侧空出的位用0或符号位填充(取决于操作数的符号)。

例如:

let a = 5;            // 二进制表示为 0101
let result = a >> 1;  // 将二进制位右移1位,结果为 0010,即 2

3.7 索引([])运算符

索引运算符 [] 被视需要两个操作数:被索引的数据结构 和 索引值。其中,被索引的数据结构 是 左操作数,索引值 是 右操作数。通过将索引值放在方括号内,可以使用索引运算符访问数据结构中的特定元素。被索引的数据结构 可以是很多种,比如数组、向量、字符串等等。

3.7.1 数组的索引

Rust 数组内置索引能力,可以通过索引运算符按照位序获取元素。例如:

let arr = [1, 2, 3, 4, 5];
let element = arr[2];  // 获取索引为2的元素,结果为3
arr[3] = 10;           // 修改索引为3的元素为10

3.7.2 向量的索引

Rust 向量内置索引能力,可以通过索引运算符按照位序获取元素。例如:

let vec = vec![1, 2, 3, 4, 5];
let element = vec[3];  // 获取索引为3的元素,结果为4
vec[1] = 7;            // 修改索引为1的元素为7

3.7.3 字符串的索引

《Rust 语言中的字符串》 中详细介绍了 strString。其中我们说过字符串类型 str 是一种不可变的的字符,这种字符串类型 不支持通过索引运算符直接对其进行索引。这是因为 str 类型是一个不固定长度的 UTF-8 字符串,直接通过索引访问可能会导致不正确的操作。

好在 Rust 语言中还有一种可变字符串String。String 类型是支持通过索引运算符对其进行索引的。它可以使用索引运算符 [] 并传递一个整数索引来访问 String 中的字符。例如:

let mut s = String::from("Hello, Rust!");
// 通过索引访问和修改字符
let first_char = s[0];
s[7] = 'W';
println!("First character: {}", first_char);
println!("Modified string: {}", s);

3.8 调用(())运算符

调用运算符 () 用于调用函数或方法,将函数或方法名称与一对括号组合在一起,允许你执行函数或方法并传递参数。

例如我们可以定义一个独立的函数,或者在结构体中定义一个方法:

fn hello(name: &str) {
    println!("Hello, {}!", name);
}
struct Person {
    name: String,
}
impl Person {
    fn greet(&self) {
        println!("Hello, {}!", self.name);
    }
}

然后在需要使用的地方通过 调用运算符 调用它们:

fn main() {
    hello("Alice"); // 调用函数
    // 调用方法
    let person = Person {
        name: String::from("Bob"),
    };
    person.greet(); // 输出:Hello, Bob!
}

调用运算符 () 可以用于任何 可调用项,包括函数方法闭包等。它可以带有参数,用于向被调用项传递值

3.9 解引用赋值(*=)运算符

解引用赋值运算符*=)是一种 复合运算符,它由之前介绍过的 解引运算符赋值运算符 复合而成。

*= 用于 解引用一个可变引用,并将 新的值 赋给 引用所指向的位置。它将 右侧的值解引用,并将 解引用后的值 赋给 左侧的可变引用。 例如:

let num = 42;
let num_ref = &num;
// 使用解引用运算符获取引用所指向的值
let dereferenced_num = *num_ref;
println!("Dereferenced num: {}", dereferenced_num); // 输出: Dereferenced num: 42
let mut value = 10;
let value_ref = &mut value;
// 使用解引用运算符修改引用所指向的值
*value_ref = 20;
println!("Modified value: {}", value); // 输出: Modified value: 20
目录
相关文章
|
10天前
|
Rust 安全 Java
探索Rust语言的并发编程模型
探索Rust语言的并发编程模型
|
16天前
|
Rust 安全 区块链
探索Rust语言:系统编程的新选择
【10月更文挑战第27天】Rust语言以其安全性、性能和并发性在系统编程领域受到广泛关注。本文介绍了Rust的核心特性,如内存安全、高性能和强大的并发模型,以及开发技巧和实用工具,展示了Rust如何改变系统编程的面貌,并展望了其在WebAssembly、区块链和嵌入式系统等领域的未来应用。
|
18天前
|
Rust 安全 Java
编程语言新宠:Rust语言的特性、优势与实战入门
【10月更文挑战第27天】Rust语言以其独特的特性和优势在编程领域迅速崛起。本文介绍Rust的核心特性,如所有权系统和强大的并发处理能力,以及其性能和安全性优势。通过实战示例,如“Hello, World!”和线程编程,帮助读者快速入门Rust。
36 1
|
19天前
|
Rust 安全 编译器
编程语言新宠:Rust语言的特性、优势与实战入门
【10月更文挑战第26天】Rust语言诞生于2006年,由Mozilla公司的Graydon Hoare发起。作为一门系统编程语言,Rust专注于安全和高性能。通过所有权系统和生命周期管理,Rust在编译期就能消除内存泄漏等问题,适用于操作系统、嵌入式系统等高可靠性场景。
29 2
|
10天前
|
Rust 安全 前端开发
探索Rust语言的异步编程模型
探索Rust语言的异步编程模型
|
20天前
|
Rust 安全 云计算
Rust语言入门:安全性与并发性的完美结合
【10月更文挑战第25天】Rust 是一种系统级编程语言,以其独特的安全性和并发性保障而著称。它提供了与 C 和 C++ 相当的性能,同时确保内存安全,避免了常见的安全问题。Rust 的所有权系统通过编译时检查保证内存安全,其零成本抽象设计使得抽象不会带来额外的性能开销。Rust 还提供了强大的并发编程工具,如线程、消息传递和原子操作,确保了数据竞争的编译时检测。这些特性使 Rust 成为编写高效、安全并发代码的理想选择。
15 0
|
1月前
|
Rust 安全 网络安全
在 Rust 语言中,寻找企业上网行为管理软件的突破
在数字化企业环境中,上网行为管理软件对于保障网络安全和提升工作效率至关重要。Rust 语言凭借其安全性、高性能和并发性,为开发此类软件提供了新机遇。本文通过几个 Rust 代码示例,展示了如何实现网址检查、访问频率统计及访问控制等功能,旨在探索 Rust 在企业上网行为管理中的应用潜力。
36 0
|
3月前
|
Rust 安全 Go
揭秘Rust语言:为何它能让你在编程江湖中,既安全驰骋又高效超车,颠覆你的编程世界观!
【8月更文挑战第31天】Rust 是一门新兴的系统级编程语言,以其卓越的安全性、高性能和强大的并发能力著称。它通过独特的所有权和借用检查机制解决了内存安全问题,使开发者既能享受 C/C++ 的性能,又能避免常见的内存错误。Rust 支持零成本抽象,确保高级抽象不牺牲性能,同时提供模块化和并发编程支持,适用于系统应用、嵌入式设备及网络服务等多种场景。从简单的 “Hello World” 程序到复杂的系统开发,Rust 正逐渐成为现代软件开发的热门选择。
66 1
|
3月前
|
Rust 安全 编译器
初探 Rust 语言与环境搭建
Rust 是一门始于2006年的系统编程语言,由Mozilla研究员Graydon Hoare发起,旨在确保内存安全而不牺牲性能。通过所有权、借用和生命周期机制,Rust避免了空指针和数据竞争等问题,简化了并发编程。相较于C/C++,Rust在编译时预防内存错误,提供类似C++的语法和更高的安全性。Rust适用于系统编程、WebAssembly、嵌入式系统和工具开发等领域。其生态系统包括Cargo包管理器和活跃社区。学习资源如&quot;The Book&quot;和&quot;Rust by Example&quot;帮助新手入门。安装Rust可通过Rustup进行,支持跨平台操作。
150 2
初探 Rust 语言与环境搭建
|
3月前
|
Rust 安全 程序员
Rust 语言的防错机制太惊人了!安全编码从此不再是难题,快来一探究竟!
【8月更文挑战第31天】《安全编码原则:Rust 语言中的防错机制》探讨了代码安全的重要性,并详细介绍了Rust语言如何通过内存安全模型、所有权与借用规则等特性,在编译阶段检测并阻止潜在错误,如缓冲区溢出和悬空指针。文章还讨论了类型安全、边界检查等其他安全特性,并提出了遵循不可变引用、避免裸指针及充分测试等实用编码原则,以进一步提升代码质量和安全性。随着Rust在软件开发中的应用日益广泛,掌握其安全编码原则变得尤为重要。
58 0