Rust: Rust 运算符与表达式:从算术到位运算全掌握
最后更新:2026-08-26
在 Rust 中,几乎所有东西都是表达式——包括 if 和 match。
理解表达式(有返回值)和语句(无返回值)的区别,是写出简洁 Rust 代码的关键。
1. 你将学到
- 算术运算符:
+ - * / % - 比较运算符:
== != < > <= >= - 逻辑运算符:
&& || ! - 位运算符:
& | ^ << >> - 表达式与语句的区别
- 运算符优先级
2. 一个收银员的故事
(1) 痛苦:打折计算总是出错
Tom 是一家服装店的店长,他每天要算各种折扣:
- 买 2 件打 8 折,买 3 件打 7 折
- 满 500 减 50
- 会员额外 9.5 折
- 叠加优惠时算错顺序,导致月底对不上账,亏了 500 元
"如果有个计算器能自动按正确顺序算就好了……"
(2) Rust 的表达式方案
RUST
fn main() {
let price: f64 = 299.0; // 一件衣服 299 元
let quantity: i32 = 3; // 买了 3 件
let is_member: bool = true; // 是会员
// 一次表达式算清所有折扣
let total = (price * quantity as f64) // 原价
* if quantity >= 3 { 0.7 } else { 0.9 } // 数量折扣
* if is_member { 0.95 } else { 1.0 }; // 会员折扣
println!("原价: {:.2} 元", price * quantity as f64);
println!("折后价: {:.2} 元", total);
println!("节省: {:.2} 元", price * quantity as f64 - total);
}
Rust 的
if本身是表达式,可以直接返回值。这让打折计算变成一行表达式链,不出错。
3. 运算符一览
graph TB
A[Rust 运算符] --> B[算术: + - * / %]
A --> C[比较: == != < > <= >=]
A --> D[逻辑: && || !]
A --> E[位运算: & | ^ << >>]
A --> F[赋值: = += -= *= /=]
(1) 算术运算符
| 运算符 | 示例 | 说明 |
|---|---|---|
+ |
a + b |
加法 |
- |
a - b |
减法 |
* |
a * b |
乘法 |
/ |
a / b |
除法(整数截断) |
% |
a % b |
取余 |
- |
-a |
取负(一元) |
整数除法会截断:
5 / 2 = 2(不是 2.5)。要得到浮点结果,需要浮点类型:5.0 / 2.0 = 2.5。
(2) 比较运算符
所有比较运算符返回 bool 类型:true 或 false。
RUST
let a = 10;
let b = 20;
println!("{}", a == b); // false
println!("{}", a != b); // true
println!("{}", a < b); // true
(3) 逻辑运算符
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
&& |
逻辑与 | a && b |
两者为真才真(短路) |
| ` | ` | 逻辑或 | |
! |
逻辑非 | !a |
取反 |
短路求值:
&&左侧为 false 时右侧不执行,||左侧为 true 时右侧不执行。这可以用于"先检查再访问"模式。
(4) 位运算符
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
& |
按位与 | a & b |
对应位都为 1 才为 1 |
| ` | ` | 按位或 | `a |
^ |
按位异或 | a ^ b |
对应位不同才为 1 |
<< |
左移 | a << n |
左移 n 位(相当于乘以 2^n) |
>> |
右移 | a >> n |
右移 n 位(相当于除以 2^n) |
4. 表达式与语句
(1) 核心区别
| 概念 | 定义 | 示例 |
|---|---|---|
| 表达式 | 有返回值 | 5 + 3 返回 8,if true { 1 } else { 0 } 返回 1 |
| 语句 | 没有返回值 | let x = 5; 不返回值,fn foo() {} 不返回值 |
Rust 中分号决定表达式还是语句:
RUST
fn main() {
let y = {
let x = 3;
x + 1 // 没有分号——这是表达式,返回 4
}; // 分号结束 let 语句
println!("y 的值: {}", y); // 4
}
(2) 块表达式
{} 包裹的代码块可以是表达式,最后一行不加分号即返回值:
RUST
let result = {
let a = 2;
let b = 3;
a * b // 不加分号,此块表达式返回 6
};
5. 运算符示例
▶ 示例 1:算术运算与类型(难度 ⭐)
RUST
// ============================================
// 算术运算符演示——注意整数除法截断
// ============================================
fn main() {
let a = 10;
let b = 3;
println!("加法: {} + {} = {}", a, b, a + b);
println!("减法: {} - {} = {}", a, b, a - b);
println!("乘法: {} * {} = {}", a, b, a * b);
println!("整数除法: {} / {} = {} (截断)", a, b, a / b);
println!("浮点除法: {} / {} = {:.2}", a as f64, b as f64, a as f64 / b as f64);
println!("取余: {} % {} = {}", a, b, a % b);
}
输出:
TEXT
📖 仅展示
加法: 10 + 3 = 13
减法: 10 - 3 = 7
乘法: 10 * 3 = 30
整数除法: 10 / 3 = 3 (截断)
浮点除法: 10 / 3 = 3.33
取余: 10 % 3 = 1
as关键字用于类型转换。a as f64把整数转成浮点后再做除法,得到浮点结果。
▶ 示例 2:逻辑运算短路求值(难度 ⭐⭐)
RUST
// ============================================
// 逻辑运算符的短路求值特性
// ============================================
fn main() {
let age = 17;
let has_id = true;
// && 短路:左侧 false 则右侧不执行
let can_buy = age >= 18 && has_id;
println!("可以购买(&&): {}", can_buy); // false(因为左侧已 false)
// || 短路:左侧 true 则右侧不执行
let is_ok = true || (expensive_check());
println!("(|| 短路,右侧不会执行): {}", is_ok);
}
fn expensive_check() -> bool {
println!("这个函数不会被执行!");
true
}
输出:
TEXT
📖 仅展示
可以购买(&&): false
(|| 短路,右侧不会执行): true
短路求值是一个重要的性能优化——把开销小的检查放在左侧,开销大的检查放在右侧,避免不必要的计算。
▶ 示例 3:表达式块返回值(难度 ⭐⭐)
RUST
// ============================================
// 用表达式块实现复杂条件的简洁赋值
// ============================================
fn main() {
let score = 85;
let grade = {
if score >= 90 {
"A"
} else if score >= 80 {
"B"
} else if score >= 70 {
"C"
} else if score >= 60 {
"D"
} else {
"F"
}
}; // 注意:整个 if-else 链是一个表达式,用分号结束 let 语句
println!("分数: {}, 等级: {}", score, grade);
// 三元运算的替代:用 if 表达式
let is_pass = if score >= 60 { "passed" } else { "failed" };
println!("结果: {}", is_pass);
}
输出:
TEXT
📖 仅展示
分数: 85, 等级: B
结果: passed
Rust 没有三元运算符(
condition ? a : b),但if本身就是表达式,可以达到同样的效果,而且可读性更好。
▶ 示例 4:位运算实战——权限标志与颜色混合(难度 ⭐⭐)
RUST
// ============================================
// 位运算实战:文件权限和 RGB 颜色操作
// ============================================
fn main() {
let read_perm: u8 = 0b100; // 4
let write_perm: u8 = 0b010; // 2
let exec_perm: u8 = 0b001; // 1
let user_perm = read_perm | write_perm;
println!("用户权限: {:03b} (读+写)", user_perm);
let full_perm = read_perm | write_perm | exec_perm;
println!("完整权限: {:03b} (读+写+执行)", full_perm);
let can_read = (user_perm & read_perm) != 0;
let can_exec = (user_perm & exec_perm) != 0;
println!("用户可读: {},可执行: {}", can_read, can_exec);
let no_write = user_perm & !write_perm;
println!("移除写权限: {:03b}", no_write);
let toggled = user_perm ^ exec_perm;
println!("切换执行位: {:03b}", toggled);
let red: u32 = 0xFF0000;
let green: u32 = 0x00FF00;
let blue: u32 = 0x0000FF;
let yellow = red | green;
let white = red | green | blue;
println!("\n红色: {:06X}", red);
println!("黄色 (红|绿): {:06X}", yellow);
println!("白色 (红|绿|蓝): {:06X}", white);
let pixel: u32 = 0xFF8040;
let r = (pixel >> 16) & 0xFF;
let g = (pixel >> 8) & 0xFF;
let b = pixel & 0xFF;
println!("\n像素 #FF8040 → R={}, G={}, B={}", r, g, b);
let shift_val: u8 = 1;
println!("\n1 << 0 = {}", shift_val << 0);
println!("1 << 1 = {}", shift_val << 1);
println!("1 << 2 = {}", shift_val << 2);
println!("1 << 3 = {}", shift_val << 3);
}
输出:
TEXT
📖 仅展示
用户权限: 110 (读+写)
完整权限: 111 (读+写+执行)
用户可读: true,可执行: false
移除写权限: 100
切换执行位: 111
红色: FF0000
黄色 (红|绿): FFFF00
白色 (红|绿|蓝): FFFFFF
像素 #FF8040 → R=255, G=128, B=64
1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8
位运算在系统编程中极为常用:权限管理用
|合并、&检查、& !移除;颜色用|混合、>>+&提取通道;<<相当于乘以 2 的幂。
▶ 示例 5:运算符优先级与复合表达式(难度 ⭐⭐⭐)
RUST
// ============================================
// 运算符优先级实战 + 复合赋值运算符
// ============================================
fn main() {
println!("=== 运算符优先级 ===");
let a = 2 + 3 * 4;
println!("2 + 3 * 4 = {} (先乘后加)", a);
let b = (2 + 3) * 4;
println!("(2 + 3) * 4 = {} (括号优先)", b);
let c = 10 - 6 / 2;
println!("10 - 6 / 2 = {} (先除后减)", c);
let d = true && false || true;
println!("true && false || true = {} (&& 优先于 ||)", d);
let e = true || false && false;
println!("true || false && false = {} (&& 优先于 ||)", e);
println!("\n=== 复合赋值运算符 ===");
let mut score: i32 = 100;
score += 20;
println!("score += 20 → {}", score);
score -= 30;
println!("score -= 30 → {}", score);
score *= 2;
println!("score *= 2 → {}", score);
score /= 7;
println!("score /= 7 → {}", score);
score %= 3;
println!("score %= 3 → {}", score);
println!("\n=== 链式比较(用逻辑运算符)===");
let x = 50;
let in_range = x >= 0 && x <= 100;
let out_range = x < 0 || x > 100;
println!("x={}, 在[0,100]内: {}, 在外: {}", x, in_range, out_range);
let charlie_score = 75;
let bob_score = 88;
let both_passed = charlie_score >= 60 && bob_score >= 60;
let any_excellent = charlie_score >= 90 || bob_score >= 90;
println!("两人都及格: {}, 有人优秀: {}", both_passed, any_excellent);
}
输出:
TEXT
📖 仅展示
=== 运算符优先级 ===
2 + 3 * 4 = 14 (先乘后加)
(2 + 3) * 4 = 20 (括号优先)
10 - 6 / 2 = 7 (先除后减)
true && false || true = true (&& 优先于 ||)
true || false && false = true (&& 优先于 ||)
=== 复合赋值运算符 ===
score += 20 → 120
score -= 30 → 90
score *= 2 → 180
score /= 7 → 25
score %= 3 → 1
=== 链式比较(用逻辑运算符)===
x=50, 在[0,100]内: true, 在外: false
两人都及格: true, 有人优秀: false
运算符优先级从高到低:
* / %→+ -→ 比较运算符 →&&→||。拿不准时加括号,代码可读性比"简洁"更重要。
❓ 常见问题
Q 5 / 2 在 Rust 里等于多少?
A 等于 2(整数除法截断)。
Q Rust 有没有 ++ 和 -- 运算符?
A 没有。
Q && 和 & 有什么区别?
A && 是逻辑与(短路),& 是按位与(不短路)。
Q 表达式和语句怎么记住?
A 看结尾有没有分号。
Q as 类型转换有什么陷阱?
A
as 会静默截断数据,不报错。📖 小节
- Rust 有算术、比较、逻辑、位运算四类运算符,大部分与其他语言一致
- 整数除法会截断,需要浮点除法请用
as转换 - 逻辑运算符
&&和||具有短路求值特性 - 表达式有返回值,语句没有——分号决定一切
if本身是表达式,可以替代其他语言的三元运算符- Rust 没有
++/--,用+= 1/-= 1代替
📝 作业
- 难度 ⭐:写一个程序,用
as转换把i32类型的5和2转成f64,输出5 / 2 = 2.5。 - 难度 ⭐⭐:定义一个变量
x = 5,用表达式块{ x + 1 }给y赋值,同时注意x在表达式块外是否还能访问。 - 难度 ⭐⭐⭐:用位运算符实现一个函数
fn is_even(n: i32) -> bool,要求用&位运算(而不是%)判断奇偶性。