Rust: Rust Operators and Expressions

Last updated: 2026-08-26

In Rust, almost everything is an expression—including if and match.

Understanding the difference between expressions (which return a value) and statements (which do not return a value) is key to writing concise Rust code.


1. What You'll Learn



2. The Story of a Cashier

(1) Frustration: I always make mistakes when calculating discounts

Tom is the manager of a clothing store, and every day he has to calculate various discounts:

"It would be great if there were a calculator that could automatically perform calculations in the correct order..."

(2) Rust's Expression Scheme

RUST
fn main() {
    let price: f64 = 299.0;      // A piece of clothing 299 yuan
    let quantity: i32 = 3;        // Bought 3 items
    let is_member: bool = true;   // Is a member

    // Calculate all discounts with a single expression
    let total = (price * quantity as f64)           // Original Price
        * if quantity >= 3 { 0.7 } else { 0.9 }    // Volume Discount
        * if is_member { 0.95 } else { 1.0 };      // Member Discounts

    println!("Original Price: {:.2} yuan", price * quantity as f64);
    println!("Price after discount: {:.2} yuan", total);
    println!("Save: {:.2} yuan", price * quantity as f64 - total);
}

In Rust, if is an expression in itself and can return a value directly. This allows the discount calculation to be expressed as a single chain of expressions, eliminating the risk of errors.



3. List of Operators

100%
graph TB
    A[Rust Operators] --> B[Arithmetic: + - * / %]
    A --> C[Comparison: == != < > <= >=]
    A --> D[Logic: && || !]
    A --> E[Bitwise Operations: & | ^ << >>]
    A --> F[Assignment: = += -= *= /=]

(1) Arithmetic Operators

Operator Example Description
+ a + b Addition
- a - b Subtraction
* a * b Multiplication
/ a / b Division (Integer Truncation)
% a % b remainder
- -a Take Negative (Unary)

Integer division results in truncation: 5 / 2 = 2 (not 2.5). To obtain a floating-point result, you need to use a floating-point type: 5.0 / 2.0 = 2.5.

(2) Comparison Operators

All comparison operators return the bool type: true or false.

RUST
let a = 10;
let b = 20;
println!("{}", a == b);  // false
println!("{}", a != b);  // true
println!("{}", a < b);   // true

(3) Logical Operators

Operator Name Example Description
&& Logic AND a && b True only if both are true (short-circuit)
` ` Logical OR
! Logical NOT !a Invert

Short-circuit evaluation: &&—if the left side is false, the right side is not evaluated; ||—if the left side is true, the right side is not evaluated. This can be used in a "check-before-access" pattern.

(4) Bitwise Operators

Operator Name Example Description
& Bitwise AND a & b Equals 1 only if all corresponding bits are 1
` ` Bitwise OR `a
^ Bitwise XOR a ^ b Equals 1 only if the corresponding bits are different
<< Shift left a << n Shift left by n bits (equivalent to multiplying by 2^n)
>> Shift right a >> n Shift right by n bits (equivalent to division by 2^n)


4. Expressions and Statements

(1) Key Differences

Concept Definition Example
Expression Has a return value 5 + 3 returns 8, if true { 1 } else { 0 } returns 1
Statement No return value let x = 5; No return value, fn foo() {} No return value

In Rust, semicolons determine whether something is an expression or a statement:

RUST
fn main() {
    let y = {
        let x = 3;
        x + 1       // No semicolons -- This is an expression, Returns 4
    };               // End of semicolon let Statement

    println!("y the value: {}", y);  // 4
}

(2) Block Expressions

{} The code block within the block can be an expression; if the last line does not end with a semicolon, it returns a value:

RUST
let result = {
    let a = 2;
    let b = 3;
    a * b           // No semicolons, This expression returns 6
};


5. Examples of Operators

▶ Example 1: Arithmetic Operations and Types (Difficulty ⭐)

Output:

TEXT 📖 Display only
Addition: 10 + 3 = 13
Subtraction: 10 - 3 = 7
Multiplication: 10 * 3 = 30
Integer Division: 10 / 3 = 3 (Truncation)
Floating-Point Division: 10.0 / 3.0 = 10.0
Modulo: 10 % 3 = 1
RUST
// ============================================
// Demonstration of Arithmetic Operators——Note: Truncation in integer division
// ============================================

fn main() {
    let a = 10;
    let b = 3;

    println!("Addition: {} + {} = {}", a, b, a + b);
    println!("Subtraction: {} - {} = {}", a, b, a - b);
    println!("Multiplication: {} * {} = {}", a, b, a * b);
    println!("Integer Division: {} / {} = {} (Truncation)", a, b, a / b);
    println!("Floating-Point Division: {} / {} = {:.2}", a as f64, b as f64, a as f64 / b as f64);
    println!("Modulo: {} % {} = {}", a, b, a % b);
}

Output:

TEXT 📖 Display only
Addition: 10 + 3 = 13
Subtraction: 10 - 3 = 7
Multiplication: 10 * 3 = 30
Integer Division: 10 / 3 = 3 (Truncation)
Floating-Point Division: 10 / 3 = 3.33
Modulo: 10 % 3 = 1

Output:

TEXT 📖 Display only
Available for purchase (&&): <can_buy>

as Keywords are used for type conversion. a as f64 Convert the integer to a floating-point number before performing division to obtain a floating-point result.


▶ Example 2: Short-circuit evaluation of logical operations (Difficulty: ⭐⭐)

Output:

TEXT 📖 Display only
Available for purchase (&&): <can_buy>
(|| Short Circuit, The right side will not be executed): <is_ok>
This function will not be executed!
RUST
// ============================================
// Short-Circuit Evaluation of Logical Operators
// ============================================

fn main() {
    let age = 17;
    let has_id = true;

    // && Short Circuit: If the left is false, the right side is not executed
    let can_buy = age >= 18 && has_id;
    println!("Available for purchase (&&): {}", can_buy);  // false (Since the left side is already false)

    // || Short Circuit: If the left is true, the right side is not executed
    let is_ok = true || (expensive_check());
    println!("(|| Short Circuit, The right side will not be executed): {}", is_ok);
}

fn expensive_check() -> bool {
    println!("This function will not be executed!");
    true
}

Output:

TEXT 📖 Display only
Available for purchase (&&): false
(|| Short Circuit, The right side will not be executed): true

Output:

TEXT 📖 Display only
Score: 85, Level: <grade>

Short-circuit evaluation is an important performance optimization—it places low-cost checks on the left and high-cost checks on the right to avoid unnecessary computations.


▶ Example 3: Expression Block Return Values (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
Score: 85, Level: <grade>
Result: <is_pass>
RUST
// ============================================
// Using Expression Blocks to Implement Concise Assignments with Complex Conditions
// ============================================

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"
        }
    };  // Note: The entire if-else chain is an expression, End with a semicolon let Statement

    println!("Score: {}, Level: {}", score, grade);

    // Alternatives to Ternary Operations: Use if Expression
    let is_pass = if score >= 60 { "passed" } else { "failed" };
    println!("Result: {}", is_pass);
}

Output:

TEXT 📖 Display only
User Permissions: <user_perm> (Read+Write)
Full Permissions: <full_perm> (Read+Write+Execute)
User-readable: <can_read>, Executable: <can_exec>
Remove Write Permissions: <no_write>
Toggle the execution bit: <toggled>

Red: <red>

Rust doesn't have a ternary operator (condition ? a : b), but if is an expression in itself and can achieve the same result with better readability.


▶ Example 4: Bitwise Operations in Practice—Permission Flags and Color Mixing (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
User Permissions: <user_perm> (Read+Write)
Full Permissions: <full_perm> (Read+Write+Execute)
User-readable: <can_read>, Executable: <can_exec>
Remove Write Permissions: <no_write>
Toggle the execution bit: <toggled>

Red: <red>
Yellow (Red|Green): <yellow>
White (Red|Green|Blue): <white>

Pixel #FF8040 → R=<r>, G=<g>, B=<b>

1 << 0 = <shift_val << 0>
RUST
// ============================================
// Bitwise Operations in Practice:File Permissions and RGB Color Manipulation
// ============================================

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!("User Permissions: {:03b} (Read+Write)", user_perm);

    let full_perm = read_perm | write_perm | exec_perm;
    println!("Full Permissions: {:03b} (Read+Write+Execute)", full_perm);

    let can_read = (user_perm & read_perm) != 0;
    let can_exec = (user_perm & exec_perm) != 0;
    println!("User-readable: {}, Executable: {}", can_read, can_exec);

    let no_write = user_perm & !write_perm;
    println!("Remove Write Permissions: {:03b}", no_write);

    let toggled = user_perm ^ exec_perm;
    println!("Toggle the execution bit: {:03b}", toggled);

    let red: u32   = 0xFF0000;
    let green: u32 = 0x00FF00;
    let blue: u32  = 0x0000FF;
    let yellow = red | green;
    let white = red | green | blue;
    println!("\nRed: {:06X}", red);
    println!("Yellow (Red|Green): {:06X}", yellow);
    println!("White (Red|Green|Blue): {:06X}", white);

    let pixel: u32 = 0xFF8040;
    let r = (pixel >> 16) & 0xFF;
    let g = (pixel >> 8)  & 0xFF;
    let b = pixel & 0xFF;
    println!("\nPixel #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);
}

Output:

TEXT 📖 Display only
User Permissions: 110 (Read+Write)
Full Permissions: 111 (Read+Write+Execute)
User-readable: true, Executable: false
Remove Write Permissions: 100
Toggle the execution bit: 111

Red: FF0000
Yellow (Red|Green): FFFF00
White (Red|Green|Blue): FFFFFF

Pixel #FF8040 → R=255, G=128, B=64

1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8

Bitwise operations are extremely common in system programming: for permission management, use | to merge, & to check, and & ! to remove; for colors, use | to blend and >> + & to extract channels; << is equivalent to multiplying by a power of 2.


▶ Example 5: Operator Precedence and Compound Expressions (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
=== Operator Precedence ===
2 + 3 * 4 = 14 (Multiply First, Then Add)
(2 + 3) * 4 = <b> (Parentheses Take Precedence)
10 - 6 / 2 = 7.0 (Multiply First, Then Subtract)
true && false || true = <d> (&& Take precedence over ||)
true || false && false = <e> (&& Take precedence over ||)

=== Compound Assignment Operator ===
score += 20 → 100
score -= 30 → 100
score *= 2 → 100
score /= 7 → 100
score %= 3 → 100

=== Chain Comparison(Using logical operators)===
x=50, in [0,100]: <in_range>, Out of range: <out_range>
Both passed: <both_passed>, Someone excellent: <any_excellent>
RUST
// ============================================
// Operator Precedence in Practice + Compound Assignment Operator
// ============================================

fn main() {
    println!("=== Operator Precedence ===");
    let a = 2 + 3 * 4;
    println!("2 + 3 * 4 = {} (Multiply First, Then Add)", a);

    let b = (2 + 3) * 4;
    println!("(2 + 3) * 4 = {} (Parentheses Take Precedence)", b);

    let c = 10 - 6 / 2;
    println!("10 - 6 / 2 = {} (Multiply First, Then Subtract)", c);

    let d = true && false || true;
    println!("true && false || true = {} (&& Take precedence over ||)", d);

    let e = true || false && false;
    println!("true || false && false = {} (&& Take precedence over ||)", e);

    println!("\n=== Compound Assignment Operator ===");
    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=== Chain Comparison(Using logical operators)===");
    let x = 50;
    let in_range = x >= 0 && x <= 100;
    let out_range = x < 0 || x > 100;
    println!("x={}, in [0,100]: {}, Out of range: {}", 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: {}, Someone excellent: {}", both_passed, any_excellent);
}

Output:

TEXT 📖 Display only
=== Operator Precedence ===
2 + 3 * 4 = 14 (Multiply First, Then Add)
(2 + 3) * 4 = 20 (Parentheses Take Precedence)
10 - 6 / 2 = 7 (Multiply First, Then Subtract)
true && false || true = true (&& Take precedence over ||)
true || false && false = true (&& Take precedence over ||)

=== Compound Assignment Operator ===
score += 20 → 120
score -= 30 → 90
score *= 2 → 180
score /= 7 → 25
score %= 3 → 1

=== Chain Comparison(Using logical operators)===
x=50, in [0,100]: true, Out of range: false
Both passed: true, Someone excellent: false

Operator precedence, from highest to lowest: * / %+ - → comparison operators → &&||. When in doubt, use parentheses; code readability is more important than "conciseness."


❓ FAQ

Q What is 5 / 2 equal to in Rust?
A It equals 2 (integer division with truncation).
Q Does Rust have the ++ and -- operators?
A No.
Q What is the difference between && and &?
A && is a logical AND (short-circuit), and & is a bitwise AND (non-short-circuit).
Q How can I tell the difference between expressions and statements?
A Check if there's a semicolon at the end.
Q What are the pitfalls of type conversion with as?
A as silently truncates data without reporting an error.

📖 Summary


📝 Exercises

  1. Difficulty ⭐: Write a program that uses the as conversion to convert i32-type 5 and 2 to f64, and outputs 5 / 2 = 2.5.
  2. Difficulty ⭐⭐: Define a variable x = 5, use an expression block { x + 1 } to assign a value to y, and determine whether x is still accessible outside the expression block.
  3. Difficulty ⭐⭐⭐: Implement a function fn is_even(n: i32) -> bool using bitwise operators, where you must use & bitwise operations (not %) to determine parity.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏