Rust 中的算术和逻辑运算符和 C++ 大体相似。bool 在两门语言中一致(字面量 true 和 false 也是)。Rust 同样有类似的整数、无符号整数和浮点数的概念。然而,二者的语法有点不一样。Rust 使用 isize 表示整数,用 usize 表示无符号整数。这些类型与指针大小相同。例如,在 32 位系统上,usize 指 32 位无符号整数。Rust 同样带有定宽类型,即 u 或 i 后跟 8、16、32、64 或 128。例如,u8 指 8 位无符号整数,i32 指 32 位有符号整数。就浮点数而言,Rust 带有 f32 和 f64。
(译者注:C++11 前的整数类型的大小取决于平台;C++11 引入了定宽整数类型,但标准本身没有 128 位整数类型。目前,MSVC、GCC 和 Clang 都提供了 128 位整数类型。)
数值字面量可加后缀,以表示类型。如果没有后缀,Rust 会尝试推导类型。若无法推导,则使用 i32 或 f64(若有小数点)。例如:
fn main() {
let x: bool = true;
let x = 34; // 类型为 i32
// let x = 2147483648; // 错误:字面量超出了 `i32` 的范围
let x = 34isize;
let x = 34usize;
let x = 34u8;
let x = 34i64;
let x = 34f32;
}顺带一提,Rust 允许重复定义变量,因此上面的代码合法:每个 let 语句都会创建一个新变量 x,并覆盖之前的同名变量。由于变量默认不可修改,这一机制会比你想的更有用。
数值字面量除了以十进制形式表示外,也能以二进制、八进制、十六进制形式表示。分别使用 0b,0o 和 0x 作为前缀即可。可以在数值字面量中随意加下划线,下划线会被忽略。例如:
fn main() {
let x = 12;
let x = 0b1100;
let x = 0o14;
let x = 0xe;
let y = 0b_1100_0011_1011_0001;
}(译者注:C++ 的八进制字面量用 0 作为前缀;C++14 起,数值字面量中可添加单引号 ' 作分隔符,分隔符会被编译器忽略。)
Rust 带有字符和字符串,但由于使用 Unicode,因此和 C++ 的不太一样。此处按下不表,后面介绍指针、引用和动态数组(以及静态数组)时会提。
Rust 不会隐式转换数值类型。总的来说,Rust 的隐式转换和子类型比 C++ 的少很多。Rust 使用 as 关键字进行显式类型转换(coercion 和 cast,译者注:待补充二者区别)。任意数值类型都可以转换为另一种数值类型。as 不能用于将数值类型转换为布尔类型,但可以反过来转换。例如:
fn main() {
let x = 34usize as isize; // 将 usize 转换为 isize
let x = 10 as f32; // 将 isize 转换为 float
let x = 10.45f64 as i8; // 将 float 转换为 i8(降低精度)
let x = 4u8 as u64; // 提高精度
let x = 400u16 as u8; // 144, 降低精度(因而改变了值)
println!("`400u16 as u8` gives {}", x);
let x = -3i8 as u8; // 253,将有符号转换为无符号(变号)
println!("`-3i8 as u8` gives {}", x);
//let x = 45 as bool; // 错误!(应改写为 45 != 0)
let x = true as usize; // 将 bool 转换为 usize(结果为 1)
}Rust 带有以下运算符:
| 类型 | 运算符 |
|---|---|
| 数值 | +, -, *, /, % |
| 按位 | |, &, ^, <<, >> |
| 比较 | ==, !=, >, <, >=, <= |
| 短路逻辑 | ||, && |
上述运算符表现均与 C++ 一致,不过 Rust 对运算符操纵的类型限制严格一些:按位运算只能用于整数,逻辑运算符只能用于布尔值。Rust 带有一元运算符 -,用于取相反数。! 运算符反转布尔值,以及反转整数类型的每一位(后者和 C++ 中的 ~ 等价)。和 C++ 一样,Rust 带有复合赋值运算符,如 +=,但是没有自增和自减运算符(如 ++)。