Skip to content

Rust - Operators

An operator is a symbol that tells the compiler to perform a specific mathematical, relational, or logical operation. The values that an operator acts upon are called operands.

For example, in the expression 7 + 5, the + is the operator and 7 and 5 are the operands.

The major operators in Rust can be classified as:

  • Arithmetic Operators
  • Comparison Operators
  • Logical Operators
  • Bitwise Operators
  • Compound Assignment Operators

These operators are used for performing mathematical calculations. Note that Rust is strongly typed, so you cannot mix integer and floating-point types in an operation without explicit casting.

fn main() {
let a = 10;
let b = 3;
println!("Addition: {} + {} = {}", a, b, a + b); // 13
println!("Subtraction: {} - {} = {}", a, b, a - b); // 7
println!("Multiplication: {} * {} = {}", a, b, a * b); // 30
println!("Division: {} / {} = {}", a, b, a / b); // 3 (integer division)
println!("Modulus: {} % {} = {}", a, b, a % b); // 1 (remainder)
// Note: Rust does not support the increment (++) or decrement (--) operators.
// You must use `a += 1` or `a = a + 1` instead.
}

Comparison operators are used to compare two values and return a Boolean result (true or false).

fn main() {
let a = 10;
let b = 20;
println!("a > b is {}", a > b); // false
println!("a < b is {}", a < b); // true
println!("a >= b is {}", a >= b); // false
println!("a <= b is {}", a <= b); // true
println!("a == b is {}", a == b); // false
println!("a != b is {}", a != b); // true
}

Logical operators are used to combine multiple Boolean expressions. They use short-circuiting evaluation.

fn main() {
let is_active = true;
let has_permission = false;
// Logical AND (&&): true only if both operands are true
println!("Active AND has permission: {}", is_active && has_permission); // false
// Logical OR (||): true if at least one operand is true
println!("Active OR has permission: {}", is_active || has_permission); // true
// Logical NOT (!): inverts the boolean value
println!("NOT active: {}", !is_active); // false
}

Bitwise operators act on the individual bits of integer operands.

fn main() {
// Using unsigned 8-bit integers for clarity
let a: u8 = 0b0101_0101; // 85
let b: u8 = 0b0011_1100; // 60
println!("a = {:08b}", a);
println!("b = {:08b}", b);
println!("------------------");
// Bitwise AND (&)
println!("a & b = {:08b} ({})", a & b, a & b);
// Bitwise OR (|)
println!("a | b = {:08b} ({})", a | b, a | b);
// Bitwise XOR (^)
println!("a ^ b = {:08b} ({})", a ^ b, a ^ b);
// Bitwise NOT (!)
println!("!a = {:08b} ({})", !a, !a);
// Left Shift (<<)
println!("a << 2 = {:08b} ({})", a << 2, a << 2);
// Right Shift (>>)
println!("a >> 2 = {:08b} ({})", a >> 2, a >> 2);
// Note: Rust does not have a separate zero-fill right shift operator (>>>).
// The `>>` operator performs a logical shift (fills with 0) for unsigned integers
// and an arithmetic shift (preserves the sign bit) for signed integers.
}

These operators combine an arithmetic or bitwise operation with an assignment.

fn main() {
let mut x = 10;
println!("Initial x = {}", x);
x += 5; // equivalent to x = x + 5
println!("After x += 5, x = {}", x);
x -= 3; // equivalent to x = x - 3
println!("After x -= 3, x = {}", x);
x *= 2; // equivalent to x = x * 2
println!("After x *= 2, x = {}", x);
x /= 4; // equivalent to x = x / 4
println!("After x /= 4, x = {}", x);
x %= 3; // equivalent to x = x % 3
println!("After x %= 3, x = {}", x);
}

In Rust, many operators can be overloaded for custom types by implementing the associated traits from the std::ops module (e.g., Add for +, Sub for -, Not for !). This allows your custom types to integrate seamlessly with Rust’s standard syntax.