5.6 Operators
Rust supports most standard operators familiar from C/C++.
- Arithmetic:
+(add),-(subtract),*(multiply),/(divide),%(remainder/modulo). - Comparison:
==(equal),!=(not equal),<(less than),>(greater than),<=(less than or equal),>=(greater than or equal). These return abool. - Logical:
&&(logical AND, short-circuiting),||(logical OR, short-circuiting),!(logical NOT). Operate onboolvalues. - Bitwise:
&(bitwise AND),|(bitwise OR),^(bitwise XOR),!(bitwise NOT - unary, only for integers),<<(left shift),>>(right shift). Operate on integer types. Right shifts on signed integers perform sign extension; on unsigned integers, they shift in zeros. - Assignment:
=(simple assignment). - Compound Assignment:
+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=. Combines an operation with assignment (e.g.,x += 1is equivalent tox = x + 1). - Unary:
-(negation for numbers),!(logical NOT forbool, bitwise NOT for integers),&(borrow/reference),*(dereference). - Type Casting:
as(e.g.,let float_val = integer_val as f64;). Explicit casting is often required between numeric types. - Grouping:
()changes evaluation order. - Access:
.(member access for structs/tuples),[](index access for arrays/slices/vectors).
Key Differences/Notes for C Programmers:
- No Increment/Decrement Operators: Rust does not have
++or--. Usex += 1orx -= 1instead. This avoids ambiguities present in C regarding pre/post increment/decrement return values and side effects within expressions. - Strict Type Matching: Binary operators (like
+,*,&,==) generally require operands of the exact same type. Implicit numeric promotions like in C (e.g.,int + float) do not happen. You must explicitly cast usingas.#![allow(unused)] fn main() { let a: i32 = 10; let b: u8 = 5; // let c = a + b; // Compile Error: mismatched types i32 and u8 let c = a + (b as i32); // OK: b is explicitly cast to i32 println!("c = {}", c); } - No Ternary Operator: Rust does not have Cās
condition ? value_if_true : value_if_false. Use anifexpression instead, which is more readable and less prone to precedence errors:#![allow(unused)] fn main() { let condition = true; let result = if condition { 5 } else { 10 }; println!("Result = {}", result); } - Operator Overloading: You cannot create new custom operators, but you can overload existing operators (like
+,-,*,==) for your own custom types (structs, enums) by implementing corresponding traits from thestd::opsmodule (e.g.,Add,Sub,Mul,PartialEq). This allows operators to work intuitively with user-defined types like vectors or complex numbers.
In addition to the operators mentioned earlier, Rust uses & to create references or to specify that a type is a reference, and * to dereference a reference in order to access the original value it points to.
Operator Precedence: Largely follows C/C++ conventions (e.g., * and / before + and -, comparisons before logical operators). Use parentheses () to clarify or force a specific evaluation order when in doubt ā clarity is usually preferred over relying on subtle precedence rules.